java——集合详解
2023 1-1
day01 迭代器iterator的作用和使用
1.1 入门案例iterator.java
迭代器主要用于遍历,常用于集合
Iterator it = 集合对象.iterator();
while(it.hasNext()) {元素 = it.next();
}
增强 for循环
for(变量类型 变量 :数组/集合){*变量代表的就是集合或数组的元素*
}
示例
public class task02 {public static void main(String[] args) {Set<Integer> set =new HashSet<>();Scanner read = new Scanner(System.in);int length = read.nextInt();for(int i = 0 ;i < length ;i++){set.add(read.nextInt());}for(Integer i: set){ //这里用Integer而不用int是因为 set 已经指定了泛型Interger,这里的i代表的就是 集合或数组的元素System.out.print(i+" ");}Iterator it = set.iterator();while(it.hasNext()){System.out.print(it.next()+" ");}}
}
//输入: 5 1 2 3 4 5
//输出: 1 2 3 4 5 1 2 3 4 5
1.2 上转型对象
上转型对象思想用一个通俗的思想来了解就是:将老虎上转成动物,但是此时老虎失去了老虎的具体特性
这个例子很贴切:
- 普通对象可以操纵继承自父类的变量、子类新增的对象、继承或重写的方法、新增的方法,但是不可以操纵父类隐藏的变量(这里的隐藏指的是,父类和子类拥有重名的变量时,根据就近原则,父类的变量将被隐藏)
- 上转型对象可以操纵父类隐藏的变量、继承的变量、继承或者重写的方法(父类原本就包含的,也就是整个动物范畴的),但是却不可以操纵新增的变量,也不可以操纵新增的方法(失去了老虎的特性)
- 若想让 上转型对象使用子类新增的功能,可以将对象的上转型对象再强制转换到一个子类对象.
Tager taiger = (Tager)animal;
1.3 集合泛型
//泛型不支持基本数据类型,这里的不支持指的是 Set<Integer> 而不是 Set<int>
程序中可能通过数组来保存多个对象,因为数组长度是不可变的。JDK中提供了一些特殊的类,这些类可以存储任何对象,并且长度可变,在java中这些类被为集合。集合类位于java.util
包中。
集合分类
- 单列集合 Collection 接口
- 双列集合 Map 接口
8.1 Collection接口
java.util.Collection
是所有单列集合的父接口,因此在Collection中定义了单列集合List
和Set
通用的一些方法。
方法声明 | 功能描述 |
---|---|
boolean add(Object o) | 向集合中添加一个元素 |
boolean addAll(Collection c) | 增加一个集合(多个元素) |
void clear() | 清空集合 |
boolean remove(Object o) | 删除集合中的一个对象(元素) |
boolean removeAll(Collection c) | 删除一个集合(多个元素) |
boolean isEmpty() | 是不是空的 |
boolean contains(Object o) | 判断集合有没有这个元素 |
boolean containsAll(Collection c) | 判断集合中有没有参数集合 |
Iterator iterator() | 返回一个遍历迭代器 |
int size() | 返回集合的元素个数 |
注:addAll(Collection c) 中参数是一个单列集合,jdk17以后这种单列集合 或者 双列集合在调用时已经可以可以这样写了:
addAll(Set.of(1,2,3,4,5,6));//这里的S必须要大写,因为参数时一个单列集合对象
8.1.1 List接口
List接口继承自Collection接口,是单列集合的一个重要分支,习惯性地将实现了List接口的对象称为List集合。
方法声明 | 功能描述 |
---|---|
void add(int index,Object element) | |
boolean addAll(int index,Collection c) | |
Object get(int index) | |
Object remove(int index) | |
Object set(int index,Object element) | |
int indexOf(Object o) | |
int lastIndexOf(Object o) | |
List subList(int fromIndex,int toIndex) | |
ArrayList
extends AbstractList<E>
java.util.ArrayList类是List接口的一个实现类,此对象相当于动态的数组。
实例化ArrayList类
(不支持多线程)和Vector作为对比,但是ArrayList效率较高,用的也更多
//实例化 ArrayList
ArrayList list1 = new ArrayList(); //普通对象
//var list2 = new ArrayList();
List list3 = new ArrayList(); //上转型对象//此方法实例出的对象,是只读的(不能添加 删除 移动位置,优点是能够快速建立集合实例对象)
List list4 = List.of();//这种方法也可以实例化 对象
//list4.add(10); 此行是错误的,因为List.of() 对象是只读的String[] arr = {"java","javascript","python","html"};
//此方法实例出的对象,是只读的
List list5 = Arrays.asList(1,2,3);
//list5.add(10);List list6 = new ArrayList(list5);
注:
List list4 = List.of();//这种方法实例化对象是只读的,可以增加或删除或者移动位置
List list2 = List.of(1,2,4,6,7); list2.add(3);//这样写是错误的
ArrayList的排序
- 数字
List<Integer> list = new ArrayList<>();
List list1 = List.of(1,4,2,3,6);
list.addAll(list1);
//升序排序(默认升序)
Collections.sort(list);
Collections.sort(list,(a,b)->a-b);
//降序排序
Collections.sort(list,(a,b)->b-a);//乱序
Collections.shuffle(list);//这里参数写成list就错了,以为用.of()实例化的对象只读
- 字符串(本质还是数字,按照ASCII码)
//a-z升序Collections.sort(list);//Collections.sort(list, (a,b)->a.compartTo(b));System.out.println(list);//z-a降序Collections.sort(list,(a,b)->b.compareTo(a));System.out.println(list);//根据字符串升序,进行排序 升序Collections.sort(list,(a,b)->a.length()-b.length());System.out.println(list);//降序Collections.sort(list,(a,b)->b.length()-a.length());System.out.println(list);
- 自定义
如果使用集合工具的排序方法,Collections.sort(list)此类必须实现
Comparable接口,实现方法;而用实例的对象调用继承自 Collections.sort()方法时 ,需要用lambda表达时指定Comparable的比较方法
public class SortArrayList {public static void main(String[] args) {List<Book> list = new ArrayList<>();list.addAll(List.of(new Book("a",1),new Book("b",5),new Book("c",2)));//实现方法一//用lamda表达式来重写compareTo()方法,按照book的Id来排序list.sort((a,b)->(a.getId()-b.getId())); //,按照book的name来排序list.sort((a,b)->(b.getName().compareTo(a.getName())));//实现方法二,此时的Book 必须实现comparable接口/*public class Book implements Comparable<Book>{@Overridepublic int compareTo(Book o) {return o.name.compareTo(name); // 参数是b, 当前 book 是a}}*/Collections.sort(list);//-------------三种遍历集合的方法-----------------------//1.遍历效率低System.out.println(list);//2.遍历效率高Iterator it = list.iterator();while(it.hasNext()){System.out.print(it.next()+" ");}//3.for(Book i : list){System.out.print(i+" ");}String a = new String("wo");System.out.println(a.compareTo("a"));}
}
8.2 Map接口
map接口是一个双列集合,每个元素有一个键值 对 Map<K,V>
public interface Map<K, V> {}
8.2.1 HashMap
Map<K,V> 实现类为 HashMap<K,V>,HashMap 实例化,添加,判断,清空,删除,替换
HashMap基本使用
package cn.webrx;import java.util.HashMap;
import java.util.Map;public class HashMap1 {public static void main(String[] args) {//没有使用泛型,不推荐//Map map = new HashMap();//实例化Map对象Map<String,Book> map = new HashMap<>();//添加元素,添加元素时,如果Key值存在,则覆盖元素map.put("b01",new Book(10,"《java程序入门》",35));map.put("b02",new Book(22,"《数据库技术》",55));Book book = new Book(33,"《前端开发》",30);map.put("b02",book);//判断//判断有没有Key 为 b01 trueSystem.out.println(map.containsKey("b01"));//判断有没有Key 为 b03 falseSystem.out.println(map.containsKey("b03"));//判断有没有Value 为 new Book(33,"《前端开发》",30)//System.out.println(map.containsValue(new Book(33,"《前端开发》",30)));System.out.println(map.containsValue(book));//编辑,重新设置或修改值map.replace("b02",new Book(55,"《java微服务开发实战》",68));//删除清空//map.clear();//map.remove("b02");//获取指定元素 get(String key)System.out.println(map.get("b01"));System.out.println(map.get("b11"));//获取指定key元素,如果不存在,则使用默认值返回对象System.out.println(map.getOrDefault("b11",new Book(100,"《入门书籍》",35)));System.out.println(map.getOrDefault("b02",new Book(100,"《入门书籍》",35)));//获取map集合的元素个数System.out.println(map.size());System.out.println(map);}
}
HashMap遍历KeySet Values
package cn.webrx;import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;public class HashMap2 {public static void main(String[] args) {Map<String,String> map = new HashMap<>();map.put("bj","北京");map.put("tj","天津");map.put("hn","河南");map.put("sh","上海");//第一种遍历方式 keySet()方法返回Set集合Set<String> keys = map.keySet();for(String k : keys){//System.out.println(k);System.out.printf("map[\"%s\"] = %s%n",k,map.get(k));}//第二种遍历方式 values() 返回Collection<String> 集合Collection<String> values = map.values();for(String v : values){System.out.println(v);}//第三种遍历方式 entrySet() 返回一个Set<Map.Entry<String,String>> 集合Set<Map.Entry<String, String>> entries = map.entrySet();for(Map.Entry<String,String> e : entries){//System.out.println(e);System.out.println(e.getKey());System.out.println(e.getValue());}//第四种遍历方式 使用迭代器接口Iterator 接口Iterator<String> iterator = map.values().iterator();while(iterator.hasNext()){System.out.println(iterator.next());}Iterator<String> iterator1 = map.keySet().iterator();while(iterator1.hasNext()){String key = iterator1.next();System.out.println(key);System.out.println(map.get(key));}}
}
以上遍历主要Iterator遍历集合方式、for循环遍历集合方式,Lambda遍历集合方式,根据具体需求选用不同的方式,通过Iterator方式循环删除数据是安全的,for方式循环删除数据非安全,Lambda方式循环删除 数据非安全,通过Iterator方式的效率也很高
HashMap不是线程同步,如果需要使用线程并发,可以使用HashTable对象
Hashtable<K,V> implements Map<K,V>
Hashtable:底层也是哈希表,是同步的,是一个单线程结合,是线程安全的集合,速度慢
HashMap:底层也是哈希表,但是线程不安全的集合,是多线程集合,速度快
HashMap(还有之前学的所有集合):都可以存储null键,null值
Hashtable:不能存储null键,null值
8.2.2 TreeMap
是一个有序的key-value集合,它是通过红黑树实现的。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
是继承了AbstractMap,也是以key-value集合存储。实现了NavigableMap接口,可以支持一系列的导航方法。
比如返回有序的key集合。实现了Cloneable克隆接口。实现了java.io.Serializable序列化接口。另外,TreeMap是非线程同步的。
构造方法
TreeMap() 使用键的自然顺序构造一个新的、空的树映射。
TreeMap(Comparator comparator) 构造一个新的、空的树映射,该映射根据给定比较器进行排序。
TreeMap(Map m) 构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序。
TreeMap(SortedMap m) 构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。
TreeMap<String, Integer> tm = new TreeMap<>();
TreeMap<String, Integer> tm = new TreeMap<>((a, b) -> Math.random() > .5 ? 1 : -1);
TreeMap<String, Integer> tm = new TreeMap<>((a, b) -> a.compareTo(b));
TreeMap<String, Integer> tm = new TreeMap<>(Comparator.reverseOrder());
TreeMap<String, Integer> tm = new TreeMap<>((a,b)->b.compareTo(a));
TreeMap<String, Integer> tm = new TreeMap<>((a,b)->a.compareTo(b));
TreeMap<String, Integer> tm = new TreeMap<>(String::compareTo);//升序
TreeMap<Double, String> t2 = new TreeMap<>();
//TreeMap<Double, String> t2 = new TreeMap<>(Double::compareTo);//乱序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> Math.random()>.5 ? 1 : -1);//降序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> a < b ? 1 : -1);//升序
//TreeMap<Double, String> t2 = new TreeMap<>((a, b) -> a > b ? 1 : -1);TreeMap<Student, String> t3 = new TreeMap<>((a,b)->a.getId()-b.getId());
//key String
t3.put(new Student(1,"李四1"),"郑州");
t3.put(new Student(6,"李四2"),"北京");
t3.put(new Student(2,"李四3"),"天津");
t3.put(new Student(33,"李四33"),"上海");
t3.put(new Student(4,"李四5"),"上海");
System.out.println(t3);
常用方法
方法 | 说明 |
---|---|
public NavigableMap<K,V> descendingMap() | 把集合逆序返回 |
方法 | 说明 |
---|---|
put(K key, V value) | 将指定值与此映射中的指定键进行关联 |
int size() | 返回此集合元素的个数 |
V remove(Object key) | |
putAll(Map map) | 将指定映射中的所有映射关系复制到此映射中 |
Collection values() | |
Set keySet() | 本质是TreeSet |
Map.Entry<K,V> entrySet() | 返回Set<Map.Entry<K,V>> |
get(Object key) | |
containsKey(Object key) | |
firstEntry() | 返回集合第一个Map.Entry<K,V> |
lastEntry() | |
firstKey() | 返回集合第一个元素的Key |
lastKey() | |
boolean remove(Object key, Object value) | |
containsValue() |
public static void main(String[] args) {TreeMap<Integer, String> tm = new TreeMap<>();tm.put(1, "hello1");tm.put(2, "hello22");tm.put(3, "hello333");tm.put(10, "hello10");tm.put(4, "hello4444");System.out.println(tm);//.descendingMap() 返回一个Map 根据key降序,对原来的TreeMap没有改变Map<Integer,String> t2 = tm.descendingMap();System.out.println(tm);System.out.println(t2);
}
集合总结
Collection List ArrayList LinkedList
Set HashSet TreeSetMap Iterator 接口 HashMap TreeMap
ArrayList LinkedList
HashSet TreeSet
HashMap TreeMapVector
HashTable
Vetcor
java.util.Vector
Vector 类实现了一个动态数组。和 ArrayList 很相似,但是两者是不同的:
- Vector 是同步访问的。(非线程安全、
线程安全
) - Vector 包含了许多传统的方法,这些方法不属于集合框架。
Vector 主要用在事先不知道数组的大小,或者只是需要一个可以改变大小的数组的情况。
Vector和ArrayList功能是一样的,ArrayList是非线程安全,在多线程使用中同步操作时,会出现脏读,Vetctor的各个方法添加了同步锁
synchronized
支持线程安全。在单线程程序中,ArrayList使用的最多,速度快,在多线程编程中,如果线程间在同步数据,应该使用Vector。
HashTable
和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。
Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6o60J431-1672750446862)(assets/image-20221107173855061.png)]
HashTable是线程安全的,HashMap是非线程安全。如果在单线程main线程程序中,使用了线程安全的工具类,效率就低,根据使用量上来说还是HashMap使用的多。
集合接口及工具类总结:
Collection 接口
List 接口
ArrayList 动态数组,有序 插入删除速度慢,读取速度
LinkedList 双向链表,插入删除速度快,读取速度慢
Vector 动态数组,线程安全
Set 接口
HashSet 唯一集合,无序
TreeSet 唯一集合,是有序Map 接口
HashMap K,V键值对集合,双列集合
TreeMap 根据key有序的map集合
Hashtable 和 HashMap一样,双列集合,线程安全
java——集合详解相关推荐
- Java集合详解6:TreeMap和红黑树
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- 【Java-Java集合】Java集合详解与区别
[Java-Java集合]Java集合详解与区别 1)概述 2)集合框架图 2.1.总框架图 2.2.Iterable 框架图 2.3.Map 框架图 3)List 3.1.ArrayList 类继承 ...
- Java集合详解4:HashMap和HashTable
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- Java集合详解5:深入理解LinkedHashMap和LRU缓存
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- Java集合详解之Map
一.首先看看集合框架体系图 从图中可以看到,Map接口扩展了Iterator接口,关于Iterator接口详解请移步:Iterator接口详解 二.Map是什么? Map<k,v>使用键值 ...
- 硬核干货Java集合详解
目录 一.问题是最好的老师 二.集合的由来 三.数组存在的问题 四.数组和集合的区别? 五.集合是什么? 六.集合整体架构图 七.集合架构图详解 1.Collection 2.List ArrayLi ...
- Java集合详解9:2021年的hashmap面试题怎么考?涵盖性能优化、扩容、并发问题等核心考点
摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型.随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例 ...
- Java 集合详解,常用集合类
一. java集合类图 1. 简单版: 2. 图二: 3. 图三 上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如Abstrac ...
- Java集合详解(非常详细!!!)
前言 数据结构作为每一个开发者不可回避的问题,而 Java 对于不同的数据结构提供了非常成熟的实现,这一个又一个实现既是面试中的难点,也是工作中必不可少的工具,在此,笔者经历漫长的剖析,将其抽丝剥茧的 ...
- Java集合详解2:LinkedList和Queue
今天我们来探索一下LIterator,fail-fast机制与比较器的源码. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 喜欢的话麻烦star一 ...
最新文章
- 【转载】Unix编程艺术——Unix哲学
- Crawler之Scrapy:Scrapy简介、安装、使用方法之详细攻略
- BZOJ 2115 [Wc2011] Xor ——线性基
- HOW-TO:具有MySQL的JEE应用程序中具有集群功能的Quartz Scheduler
- 使用MarkDown+mermaid-JS绘制简单图形
- Discuz 论坛实现qq小程序
- 三十一、K8s供应链安全2 - 镜像的检测及优化与yaml文件安全
- 安装项目管理工具 SVN+Redmine
- 如何在js中直接使用id_node.js中的npm update如何使用
- 简单的springboot应用,日志,静态资源配置
- CAXA图文档2007服务器端,caxa电子图板2007
- QT等待动态图gif加载透明背景lable
- Spark Streaming系列-1、什么是Spark Streaming?
- 马云说过的计算机名言,马云说过最洗脑10名言 马云经典语录大全
- 什么是铠装光纤跳线及它的特点?
- 计算机专业基础综合408备考经验分享
- 2019JDATA店铺购买预测大赛复盘(冠军方案)
- 嵌入式硬件(一)概述
- 直播软件app开发:如何开发一个可以免费打扑克的直播应用?
- 跟着团子学SAP PS:增加WBS元素为分摊发送方提升单个项目内部成本精准归集 KSV1/KSU1