在这篇文章中,我们主要讨论两类容器,一类是单值类型的Collection,包括List、Set和Queue;另一类是key-value型的Map。
Collections
Collection和Collections的区别是什么?
前者是一个集合接口,后者是一个针对集合类的包装类,后者服务于前者。
List
ArrayList和LinkedList的区别?
ArrayList的底层实现是数组,LinkedList的底层实现是双向链表。
可以从数组和链表的特点来说它们两个的区别。比如,查找机制和插入机制的不同。
Set
Set的最基本特点就是不含有重复元素。
我用得比较多的有HashSet和TreeSet。
HashSet
HashSet的底层是HashMap(之后我们会再详细说说HashMap的底层实现机制)。HahsSet只取HashMap中的key,而value是一个共享的值,这样做可以节省空间。
HashSet有如下特点:
- 不维护数据插入的顺序,也不保证数据有序
- 非线程安全
LinkedHashSet
维护了数据插入的顺序,底层实现是LinkedHashMap。
TreeSet
TreeSet中的数据默认是按自然顺序排序的。
什么是自然顺序呢?Java8文档中给出了解答:
我的理解是按1、2、3、4、5这样的自然数的顺序去排序,而不是像字典序一样按1、11、12、13、2的顺序去排。
Queue
此处要讨论的是针对并发环境下的阻塞队列模型,其设计的初衷是为了解决生产者-消费者问题。
ArrayBlockingQueue
特点:
- 基于数组实现
- 维护队头和队尾两个int变量
LinkedBlockingQueue
特点:
- 基于链表实现
- 使用双锁队列算法(两个ReentrantLock(重入锁)),可以同时进行读和写操作,
- 吞吐量更大,但需要注意死锁的问题
PriorityBlockingQueue
- 基于用数组实现的小根堆,所以队头元素也是最小的元素
- 不定长,可扩容,但最大容量为Integer.MAX_VALUE-8
ConcurrentLinkedQueue
使用循环+CAS(compare and swap)实现线程安全,类似状态机的思想
DelayQueue
延迟队列,有一个getDelay()方法,用于获取剩余延迟时间;兼具 LinkedBlockingQueue(线程安全机制)和 PriorityBlockingQueue(元素优先顺序)的特性
至此,Queue的部分就结束了。
但我还想多补充一点,因为queue这个词让我想起了和它很相似的deque(双端队列)。
关于java中的stack所应使用的数据结构,java8官方文档是这样写的:
官方推荐使用Deque来作为stack。
Map
HashMap
java8的HashMap代码较之前有了较大改动,因为现在企业标准且最低配是8,涉及到一些很多框架时都已经11起步了,所以此处仅讨论java8版本的hashmap底层实现。
- 用到的数据结构:数组+链表+树
- 算法流程:采用hash算法存储key,当有冲突时,新增链表节点,若链表深度达到或超过阈值(TREEIFY_THRESHOLD-1=7),就被重构为红黑树。
多线程环境中建议使用ConcurrentHashMap。
TreeMap
使用红黑树实现
LinkedHashMap
比HashMap多维护了一个双向列表
HashMap和HashTable的区别?
| HashMap | HashTable |
|---|---|
| 非线程安全 | 线程安全 |
| 最多允许一个key为null,不允许多个value为null | 不允许null |
| containsKey和containsValue | contains |
| 使用迭代器 | 使用枚举 |
| 默认16,指数级增长 | 数组默认大小为11,增长方式线性增长(2*old+1) |
| 在原基础上重写hashCode | hash值直接使用对象的hashCode |
关于iterator: 在使用最基础的iterator遍历的过程中,不要进行增删操作,否则会因改变对象数目而抛出异常,但有一种专门针对List的ListIterator,可从两个方向遍历List,且支持过程中对元素的修改。
如官方文档所述:它的实现机制是这样的:
ConcurrentHashMap和HashTable的区别
| ConcurrentHashMap | HashTable |
|---|---|
| 使用更细粒度的锁 | 使用synchronized修饰 |
| HashEntry中的元素几乎final来保证数据一致性 |
注意事项:为了保证使用ConcurrentHashMap时的多线程安全,最好使用原子操作,非原子操作则加锁。