Java集合详解
- 一、基本概要
- 1.什么是集合
- 2.常见的集合有哪些
- 二、基本知识
- 1.集合框架底层数据结构
- 1.1 Collection
- 1.2 Map
- 2.线程安全的集合
- 三、集合具体讲解
- 0.前沿知识
- 0. ❤关于Iterator 迭代器
- 1.Iterator迭代器是什么?用来干什么?(用来遍历集合元素)
- 2.迭代器怎么用?他的特点是什么?
- 3.如何边遍历边移除 Collection 中的元素?
- 4. ❤遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?
- 4.1 集合遍历方式:
- 4.2 集合遍历最佳实践
- 1.Collection接口下的集合
一、基本概要
Collection 和 Collections 有什么区别?
java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行
排序
、搜索
以及线程安全
等各种操作。
1.什么是集合
集合:用于存储数据的容器
2.常见的集合有哪些
两个接口:Collection + Map
-
- Collection
- List 有序有重复
- Set 无序无重复
Collection集合主要有List和Set两大接口
- List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可 以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。
- Set:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。
-
- Map
存储形式:键值对key-value
- Map是一个键值对集合,存储键、值和之间的映射
- Key无序,唯一;
- value 不要求有序,允许重复。
- Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
- Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap
- Map
总结:Map 接口 和 Collection 接口是所有集合框架的父接口:
- Collection接口的子接口包括:Set接口和List接口
- Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
- Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
- List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
二、基本知识
1.集合框架底层数据结构
1.1 Collection
-
❤List
- ArrayList: Object数组
- Vector: Object数组
- LinkedList: 双向循环链表
-
❤Set
- HashSet(无序,唯一):基于 HashMap 实现的,底层采用 HashMap 来保存元素
- LinkedHashSet: LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的。
- TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树。)
1.2 Map
-
❤HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突);
JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间;
-
❤LinkedHashMap:LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。
另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
-
❤HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
-
❤TreeMap: 红黑树(自平衡的排序二叉树)
2.线程安全的集合
- vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
- statck:堆栈类,先进后出。
- hashtable:就比hashmap多了个线程安全。
- enumeration:枚举,相当于迭代器。
- currentHashMap:current包下的
三、集合具体讲解
0.前沿知识
0. ❤关于Iterator 迭代器
1.Iterator迭代器是什么?用来干什么?(用来遍历集合元素)
Iterator 接口提供遍历任何 Collection 的接口。
我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。
迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
2.迭代器怎么用?他的特点是什么?
Iterator 使用代码如下:以ArrayList为例
List<String> list = new ArrayList<>(); Iterator<String> it = list. iterator(); while(it. hasNext()){ String obj = it. next(); System. out. println(obj); }
Iterator 的特点:
只能单向遍历,但是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
3.如何边遍历边移除 Collection 中的元素?
边遍历边修改 Collection 的唯一正确方式是使用 Iterator.remove() 方法,如下:
Iterator<Integer> it = list.iterator();
while(it.hasNext()){*// do something*it.remove();
}
一种最常见的错误代码如下:
for(Integer i : list){list.remove(i)
}
//
运行以上错误代码会报 ConcurrentModificationException 异常。
这是因为当使用 foreach(for(Integer i : list)) 语句时,
会自动生成一个iterator 来遍历该 list,
但同时该 list 正在被 Iterator.remove() 修改。
Java 一般不允许一个线程在遍历 Collection 时另一个线程修改它。
4. ❤遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么?
4.1 集合遍历方式:
有以下几种
-
for 循环遍历,基于计数器。在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。😊ArrayList使用最佳,不建议LinkedList使用,Set不能用
-
迭代器遍历,Iterator。Iterator 是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的接口。Java 在 Collections 中支持了 Iterator 模式。😊Set只能用迭代遍历;LinkedList也可用
-
foreach 循环遍历。foreach 内部也是采用了 Iterator 的方式实现,使用时不需要显式声明 Iterator 或计数器。优点是代码简洁,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。😊LinkedList可以用
4.2 集合遍历最佳实践
Java Collections 框架中提供了一个 RandomAccess 接口,用来标记 List 实现是否支持 Random Access。
如果一个数据集合实现了该接口,就意味着它支持 Random Access,按位置读取元素的平均时间复杂度为 O(1),如ArrayList。如果没有实现该接口,表示不支持 Random Access,如LinkedList。推荐的做法就是,支持 Random Access 的列表可用 for 循环遍历,否则建议用 Iterator 或 foreach 遍历。
1.Collection接口下的集合
ArrayList + LinkedList+Vector