Collection 笔记
判断线程安全类的准则
当需要在多线程环境下,使用一些类时,我们首先就需要判断当前类是否是线程安全的,否则出现线程安全问题。
准则一
最直接,方便的准则就是查看类的源代码注释,上面提到的集合类都在注释声明了该类不是线程安全的。查找注释的时候可以直接搜索 Thread
或者 synchronize
关键字。
准则二
查看有没有使用同步语句:java.util.concurrent.* / synchronize / Object.wait()
如果以上准则都不满足,几乎可以断定不是线程安全的类。
多线程环境下使用 Collection
多线程换环境下使用 ArrayList
- 最好的办法是使用
Collections.sysnchronized(new ArrayList())
- 慎用 CopyOnWriteArrayList,性能问题
多线程换环境下使用 HashSet / HashMap
- HashMap 无脑使用
ConcurrentHashMap
替换 - HashSet 没有对应的
ConcurrentHashSet
类,可使用以下方法Collections._newSetFromMap_(new ConcurrentHashMap<>());
从一个 ConcurrentHashMap 获取 HashSet- Guava 提供的
Sets._newConcurrentHashSet_();
方法,创建一个线程安全的 Set。
多线程换环境下使用 TreeSet / TreeMap
- 使用
ConcurrentSkipListSet
和ConcurrentSkipListMap
(很少使用到),都是基于 Skip List 这一数据结构实现的。
多线程环境下新的 Collection 类
- BlockingQueue 可以等待的队列。
- 当队列为空的时候,获取元素就会进入等待状态,直到队列中有元素。插入元素时相反。
- 使用场景很高级,很少使用到。一旦使用上,就要格外的小心。
- 常用的实现 ArrayBlockingQueue,SynchronousQueue。
Collection 工具方法集合
返回一个空集合
1 |
|
emptySet,emptyMap,emptyList,返回一个空集合。该空集合是全局唯一的,并且自动泛型化,在方法返回的时候很适用,节省时间和内存。
将集合变成线程安全的
1 |
|
synchronizedList,synchronizedMap,synchronizedSet 把制定的集合变成线程安全的。实际上只是把对应的集合中的方法加锁,优先使用 Concurret
集合类。
将集合变成不可变的(只读)
1 |
|
unmodifiableList,unmodifiableSet,unmodifiableMap 把指定的集合变成不可变的集合(也可以使用 Guava 的 Immutable )。
Queue 与 Deque
Queue 是数据结构中的经典的「队列」,一个方向进,一个方向出。
Deque 是「双端队列」,两个方向都可以进出。
Queue 和 Deque 的常用实现是 LinkedList。
Vector 和 Stack
Vector 就是 ArrayList 的前生。
Stack 是数据结构中经典的「栈」,使用它的好处就是能够让人一眼看出你的意图。
**Vector 和 Stack 都是 JDK 中非常古老的 class,并不是 interface! **两个类都不推荐使用,前者可以用 ArrayList 代替,后者可用 Deque 代替。
PriorityQueue
优先级队列,根据优先级进行排列。基于数据结构二叉堆(特殊的二叉树)实现,根节点的元素比所有子节点的元素都小。因此可以快速获取最大和最小元素。
PriorityQueue 的实现必须提供比较器,在初始化队列的时候提供,或者由包含的元素提供。如果两个都不提供比较器,则报错。该优先级队列非线程安全。
与 TreeSet 区别:数据结构不同,检索速度非常快(复杂度 O(1)),移除元素调整比 TreeSet 更快,遍历不保证有序。
Guava 对 Collection 体系的有力扩展
快速创建一个集合
1 |
|
Lists / Sets / Maps,方便的工具方法 newArrayList() / newLinkedList() / newHashSet() / newHashMap() 等,快速创建一个集合。
快速创建一个不可变的 Map
1 |
|
ImmutableMap 快速创建一个不可变的 Map,如果 Map 中的元素较少,可以使用 of 方法,元素较多使用 builder 方法。
创建特殊的 Set 和 Map
1 |
|
Multiset 可以记录重复插入元素的次数,MultiMap 支持同一个键插入多个元素。
BiMap
1 |
|
BiMap 是一个双向 Map,既可以键映射到值,也支持值映射到键。