Java集合对比

java基础

Posted by dks on June 17, 2019

我们所说的 Java 集合即 Java 集合框架(Java Collections Framework, JCF),本文侧重于集合类的对比及应用场景,而 API 及其具体实现可参考JCFInternals。第一部分是相关接口、类的继承关系,第二部分是具体集合类的特性与对比。

继承关系

Java 的集合类主要由两个接口派生而出:Collection 和 Map,Collection 和 Map 是 Java 集合框架的根接口。继承关系如以下两图所示,其中虚线框表示接口,实线框表示类。 Collection Map

特性

从应用场景来看,Java集合大致可以分为Set、List、Queue(三者为Collection)和 Map 四种体系,其中 Set 代表无序、不可重复的集合;List 代表有序、可重复的集合;而 Map 则代表具有映射关系的集合,Java 5 又增加了 Queue 体系集合,代表一种队列集合实现。

1.List

List 继承自 Conllection ,元素以线性方式存储,集合中可以存放重复对象。

  • ArrayList:底层基于动态数组,多用于随机访问。
  • Vector:和 ArrayList 类似,但它是线程安全的。
  • LinkedList:基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双向队列。多适用于插入、删除操作。

2.Set

继承自 Conllection, 真正数学意义上的集合抽象,不包含重复元素,更准确的说是不满足e1.equals(e2)的元素。 从实现方式上来看,Set 仅仅是对 Map 做了一层包装,也就是说 Set 里面有一个 Map(适配器模式)。

  • HashSet:基于 HashMap 的 Set 实现。为实现快速查找,不支持有序性操作。
  • LinkedHashSet:基于LinkHashMap实现,具有与 HashSet 同样的查询速度,内部使用链表维护元素的插入的次序。
  • TreeSet:基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN)。
  • EnumSet:值为枚举类型的 Set。
  • BitSet:值为比特类型的 Set。

3.Queue/Deques

  • LinkedList:可以用它来实现双向队列。详见前文。
  • ArrayDeque:Deque 是基于有首尾指针的数组(环形缓冲区)实现的。和 LinkedList 不同,这个类没有实现 List 接口。因此,如果没有首尾元素的话就不能取出任何元素。这个类比LinkedList 要好一些,因为它产生的垃圾数量较少(在扩展的时候旧的数组会被丢弃)。
  • Stack:一种后进先出的队列。已废弃,使用 Deque 来代替(首选 ArrayDeque )。
  • PriorityQueue:基于堆结构实现,可以用它来实现优先队列。

4.Map

元素以键值对的形式存储, 基本同样接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定“键”等价的策略等各不相同。标准Java类库定义了HashMap,,TreeMap,LinkedHashMap,WeakHashMap,IdentityHashMap。

  • HashMap:基于哈希表实现。
  • LinkedHashMap:类似于 HashMap ,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时反而更快,因为它使用链表维护内部次序。
  • TreeMap:基于红黑树数据结构(二叉查找树)的实现。查看“键”或“键值对”时,它们会被排序(次序由 Comparabel 或 Comparator 决定)。主要特点在于,得到的结果是经过排序的。TreeMap是唯一的带有 subMap() 方法的 Map ,它可以返回一个子树。
  • HashTable:和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。它是遗留类,不应该去使用它。现在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁。
  • WeakHashMap:弱键(weak key)Map,Map 中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有 Map 之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。适用于构建缓存场景。
  • IdentityHashMap:使用 == 代替 equals() 对“键”作比较的 HashMap。

源码分析

参见以下内容,质量高,不再搬运。

参考资料