一.集合类结构图
蓝色对应的是接口,黄色对应的是他们各自的实现类。Iterable接口是单列集合的总接口,所有实现了Iterable接口的类都可以使用增强for循环(foreach)来遍历其中的元素。
List继承Collection,存储可重复、有序的对象;
Set继承Collection,存储不可重复、无序的对象;
Map存储键值对,提供key到value的映射,key是无序、唯一,value无序,可重复。
二.集合特性比较
集合实现类 | 底层实现 | 操作效率 | 初始容量 | 扩容机制 | 线程是否安全 |
ArrayList | 数组 | 查询快,增删慢 | 10 | 若是无参构造创建对象: (1)第一次是10; (2)第二次数组容量达到上限,开始在原有基础上扩容1.5倍。 若是有参构造创建对象: (1)数组超过默认容量,开始1.5倍扩容; (2)可以指定一个数组容量。 | 线程不安全 |
LinkedList | 双向链表 | 增删快,查询慢 | 0 | 无 | 线程不安全 |
Vector | 数组 | 查询快,增删慢 | 10 | (1)数组变为原来的2倍; (2)可以指定增长因子,用原来的数组加上增长因子的长度。 | 线程安全,方法加了synchronized同步锁 |
Stack | 数组 | 查询快,增删快 | 10 | (1)数组变为原来的2倍; (2)可以指定增长因子,用原来的数组加上增长因子的长度。 | Vector子类,线程安全,方法加了synchronized同步锁 |
集合类 | 底层结构 | 实现方式 | 初始容量 | 扩容机制 | 键值是否为null | 线程是否安全 |
HashMap | Java8以前:数组+链表Java8以后:数组+链表+红黑树 | 继承AbstractMap类 | 16 | 扩容方法为resize()方法,扩容为当前容量2倍 | 键和值都允许为null,并且放在哈希表第一个位置 | 线程不安全 |
Hashtable | 数组+链表 | 继承Dictionary类 | 11 | 扩容方法为rehash()方法,扩容为当前容量2倍+1 | 键和值都不允许为null | 线程安全,使用synchronized同步互斥锁 |
ConcurrentHashMap | Java8以前: 数组+链表 Java8以后: 数组+链表+红黑树 | 继承AbstractMap类 | 16 | 扩容方法tryPresize()方法,扩容为当前容量2倍 | 键和值都不允许为null | 线程安全,使用分段锁实现,Java8之后采用CAS机制来保证线性安全 |
集合类 | 底层实现 | 数据特点 | 初始容量 | 扩容机制 | 应用场景 |
HashSet | 底层是基于HashMap,HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储一个PRESENT。 数组+链表 在Java8之后又引入红黑树 | 单列集合,无序存储,不可重复 | 16 | 扩容为数组2倍 | 单列集合中,适用于集合要求去重,查询效率高的场景 |
HashMap | Java8以前: 数组+链表 Java8以后: 数组+链表+红黑树 | 双列集合,无序存储,键不可重复,值可重复 | 16 | 扩容为数组2倍 | 双列集合中,追求查询效率高,没有要求线程安全的场景 |
TreeSet | 红黑树 | 单列集合,有序存储 | 0 | 无 | 单列集合中,要求集合元素有序 |
TreeMap | 红黑树 | 双列集合,有序存储 | 0 | 无 | 双列集合中,要求集合元素有序存储 |