概述
Java集合框架在每个jdk版本都有可能增加新的工具类,本人写这篇文章不保证是最全的集合框架,尽量保证此文章有遗漏或者滞后时会及时更新文章内容。此文章主要是框架工具类概览。如果想了解重点(HashMap,ConcurrentHashMap等)详细内容,请读者跳转具体详述文章查看。
以下文字描述为杂记和历史发展内容,不感兴趣的小伙伴可直接忽略。
结构划分方面:集合框架是用于将若干元素放入到一个容器之中,常见的为俩种。分为Map键值对存储和Collection单一元素存储。
线程安全方面:最早集合框架1.0版本只有Vector和HashTable。估计开发者认为集合框架应该都是线程安全的。因此Vector和HashTable所有方法都加了synchronized。但是synchronized毕竟影响效率,所以后期又加入了HashMap和ArrayList等线程非安全工具类。但是又暴露出线程安全问题。最后又在java.util.concurrent包中逐步增加ConcurrentHashMap等并发安全的工具类。
Map
Map是键值对key-value的集合框架。常用于根据key值找对应的value,如果调用put时key值重复则覆盖老的值。
实现类 | 数据结构 | 线程安全 | 引入版本 | 简述 |
---|---|---|---|---|
HashTable | 数组+链表 | 是 synchronized | 1.0 | 1. 初始容量为11,负载因子为 0.75。 |
HashMap | 数组+链表+红黑树(1.8) | 否 | 1.2 | HashMap是集合框架中的重中之重,希望读者自行找文章查询其原理。 1. 初始容量为16,负载因子为 0.75。 2. jdk1.8之后链表增加了红黑树,提升链表的效率,链表树化的阈值是8。因为泊松分布。 |
TreeMap | 红黑树 | 否 | 1.2 | 1. 数据结构采用红黑树,所以TreeMap符合红黑树特性。因为底层使用红黑树,所以此结构为排序结构,当使用场景需要排序的Map时,可以使用此Map,排序实现原理使用的是红黑树(二叉树)的中序遍历。 |
WeakHashMap | 数组+链表 | 否 | 1.2 | 1. 数据结构采用数组+链表,初始容量为16,负载因子为0.75。 与HashMap最重要的区别是使用的弱引用,其余与HashMap几乎一样。 |
LinkHashMap | 数组+链表+红黑树(1.8) | 否 | 1.4 | 1.继承自HashMap。 2. 用链表维护Entry的顺序,默认是插入顺序。通过维护afterNodeRemoval,afterNodeInsertion,afterNodeAccess这三个方法实现的每个元素的链表结构。 与HashMap最重要的区别是使用链表维护各个Entry的顺序,其余与HashMap几乎一样。 |
IdentityHashMap | 数组+链表 | 否 | 1.4 | 1. 初始容量为32,负载因子为2/3。 2. 对象是否重复是使用引用判断。 与HashMap最重要的区别是使用引用判断对象是否一致,其余与HashMap几乎一样。 |
ConcurrentHashMap | Segment 数组+链表+红黑树(1.8) | 是 分段锁 | 1.5 | ConcurrentHashMap是集合框架中的重中之重,希望读者自行找文章查询其原理。1. 初始容量为16,负载因子为0.75。 2. 采用分段锁保证线程安全。 |
Collection
Collection是单一数据的集合框架。Collection包括List,Set和Queue。List为顺序存储的集合,Set主要用于排重。Queue用于队列处理。
Set
Set主要用于单一元素排重的集合框架。
所有Set都是用Map实现的,Set 的入参为Map的key,value为类中的固定成员变量Object。
例如HashSet
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
实现类 | 数据结构 | 线程安全 | 引入版本 | 特性简述 |
---|---|---|---|---|
HashSet | HashMap | 否 | 1.2 | 1. 底层为为HashMap,value为一个Object。 |
TreeSet | TreeMap | 否 | 1.2 | 1. 底层为为TreeMap,value为一个Object。 |
LinkedHashSet | LinkedHashMap | 否 | 1.4 | 1. 底层为为LinkHashMap,value为一个Object。 |
EnumSet | 否 | 1.5 | 1. 值为枚举的集合类。 | |
CopyOnWriteArraySet | CopyOnWriteArrayList | 否 | 1.5 | 1. 底层为CopyOnWriteArrayList。 |
ConcurrentSkipListSet | ConcurrentSkipListMap | 否 | 1.6 | 1. 底层为ConcurrentSkipListMap。 |
List
实现类 | 数据结构 | 线程安全 | 引入版本 | 特性简述 |
---|---|---|---|---|
Vector | 数组 | 是 synchronized | 1.0 | 1. 底层为数组的有序集合,默认长度为10。 2. 当添加元素时,超过长度后进行扩容。新数组的长度为原数组的2倍。 |
Stack | 数组 | 是 synchronized | 1.0 | 继承Vector 具备后进先出的特点 通过返回len -1的数组元素实现栈的特点 |
ArrayList | 数组 | 否 | 1.2 | 1. 底层为数组的有序集合,默认长度为10。 2. 默认长度为10,当添加元素时,超过长度后进行扩容。新数组的长度为原数组的1.5倍。 |
LinkList | 链表 | 否 | 1.2 | 1.底层为链表的有序集合。 2.添加元素时维护链表的指针即可,无需扩容缩容。 |
CopyOnWriteArrayList | 数组 | 是 ReentrantLock | 1.5 | 1.底层为数组的有序集合,每次增加都进行一次长度+1的扩容。 2.线程安全使用ReentrantLock,每次操作时都加锁保证线程安全。 |
queue
jdk 1.5增加的新的框架,数据结构为队列。下面主要从三部分简述,
一:直接实现 queue接口的实现类。
二:Deque双端队列。
三:BlockingQueue阻塞队列。
其中比较重点的为阻塞队列。最重要的特点增加阻塞方法:
一.put:如果队列满了,则等待阻塞当前线程。
二.take:如果队列空了,则等待阻塞当前线程。
下面表格为直接实现queue接口的实现类。
实现类 | 数据结构 | 线程安全 | 引入版本 | 特性简述 |
---|---|---|---|---|
PriorityQueue 排序队列 | 最小二叉堆 默认容量为11 | 否 | 1.5 | 1. 底层使用最小二叉堆实现排序逻辑。 |
ConcurrentLinkedQueue | 链表 | 是 cas | 1.5 | 1. 底层使用链表。 2.算法使用的是 Michael & Scott的改进版本。 |
Deque 双端队列
实现类 | 数据结构 | 线程安全 | 引入版本 | 特性简述 |
---|---|---|---|---|
ArrayDeque | 底层用的数组 初始容量为16 | 否 | 1.6 | 1. 底层使用数组实现。 |
BlockingQueue
阻塞队列,新增主要两个阻塞方法 take和put 方法。
1.put:如果队列满了,则等待。
2.take:如果队列空了,则等待。
实现类 | 数据结构 | 线程安全 | 引入版本 | 特性简述 |
---|---|---|---|---|
ArrayBlockingQueue | 底层用的数组 初始容量为16 | 是 | 1.5 | 1. 有界阻塞队列。 |
LinkedBlockingQueue | 底层用的链表 | 是 | 1.5 | 1. 无界阻塞队列(Integer最大值)。 |
SynchronousQueue | 是 | 1.5 | 1. 容量为0的单一元素阻塞队列。 2.只有一个元素,在多线程之间传递数据。 3.必须先有一个线程take.才能有另外一个线程put。 | |
PriorityBlockingQueue | 二叉堆 | 是 | 1.5 | 有序的阻塞队列常见特性如下: 1. 阻塞队列有序。 2.内部使用ReentrantLock和cas保证线程安全。 3.内部使用二叉堆保证顺序。 |
DelayQueue | 基于PriorityQueue | 是 | 1.5 | 按照等待时间排序的等待队列。 |
LinkedTransferQueue | 链表 | 是 | 1.7 | 增加transfer方法:添加完元素后等待,直到别的线程取走元素。一个线程放入,多个线程取走。 |
总结
java集合框架将会持续更新,且会不断丰富各个工具类的内容。如文章有错误之处,欢迎各位同学留言指正。十分感谢。