java.util包中集合详解
本文只是集合的概述,介绍集合之间的关系,以及各种集合的异同,不会深入介绍具体的实现,具体实现的介绍,可以参见文中提供的链接。
java集合概述
java集合整体分为collection和map两种,接口关系如下:
![](https://img.haomeiwen.com/i1212395/c8fdcd0806736437.png)
![](https://img.haomeiwen.com/i1212395/d6b0a761f03ff5c9.png)
Iterable
为了实现new loop,类需要继承Iterable,例如:
List list = new ArrayList();
for(Object o : list){
//do something o;
}
从java8开始,新增forEach
Collection
Collection定义了集合的基本操作,详细函数可以参考JavaDoc。
List
List在java.util包中的实现(其中cocurrent包中还有并行实现),主要有以下几种:
java.util.ArrayList
java.util.LinkedList
java.util.Vector
java.util.Stack
是否容许空 | 是否容许重复 | 是否有序(遍历输出保持插入顺序) | 是否线程安全 | |
---|---|---|---|---|
ArrayList | 是 | 是 | 是 | 否 |
LinkList | 是 | 是 | 是 | 否 |
Vector | 是 | 是 | 是 | 是 |
Stack | 是 | 是 | 是 | 是 |
实现类的继承整体关系如下:
![](https://img.haomeiwen.com/i1212395/4b2587596eedd173.png)
![](https://img.haomeiwen.com/i1212395/d9a2faa56eb71c23.png)
![](https://img.haomeiwen.com/i1212395/6794fb23e45e1100.png)
![](https://img.haomeiwen.com/i1212395/be838736b5b79981.png)
ArrayList是通过数组实现,LinkedList是通过双向链表实现。这样就决定了他们两个的使用范围。LinkedList在以下情况下,比较合适:1)如果数据删除、随机插入比较多;2)随机数据的读取比较少。如果随机读取多于写入,并且写入也是追加写入,那么可以使用ArrayList,但是最好预估数据量,设置ArrayList的初始大小。ArrayList和LinkedList的详细对比。实现介绍参考: 图解集合2:LinkedList
Vector和Stack也是通过数组实现,线程安全,但ArrayList和LinkedList没有保证线程安全。
是否容许空 | 是否容许重复 | 是否有序(遍历输出保持插入顺序) | 是否线程安全 | |
---|---|---|---|---|
ArrayList | 是 | 是 | 是 | 否 |
LinkList | 是 | 是 | 是 | 否 |
Vector | 是 | 是 | 是 | 是 |
Stack | 是 | 是 | 是 | 是 |
Set
Set中元素不可以重复。在java.util包中的实现,主要有以下几种:
java.util.EnumSet
java.util.HashSet
java.util.LinkedHashSet
java.util.TreeSet
EnumSet可以应用在枚举分组时,详细介绍可以参考《Java中的EnumSet》。
![](https://img.haomeiwen.com/i1212395/20752687d4e01f84.png)
![](https://img.haomeiwen.com/i1212395/f13076face1eaa8b.png)
![](https://img.haomeiwen.com/i1212395/2484b90035c63329.png)
![](https://img.haomeiwen.com/i1212395/77d1db26b0d3f160.png)
HashSet
是使用HashMap
实现的,元素无序。 add,delete和contain
方法具有恒定的时间复杂度O(1)
。 TreeSet
是使用树结构(红黑树TreeMap
)实现的,集合中的元素是有序的,指的是排序。但add,delete 和contain
方法的时间复杂度为O(log(n))
,提供了几种方法first(),last(),headSet(),tailSet()
处理有序集(SortedSet中定义)。LinkedHashSet
介于HashSet
和TreeSet
之间,是LinkedHashMap
来实现的,提供了插入的顺序。 基本方法的时间复杂度是O(1)。详情参考《HashSet vs. TreeSet vs. LinkedHashSet》。
是否容许空 | 是否容许重复 | 是否有序(遍历输出保持插入顺序) | 是否线程安全 | |
---|---|---|---|---|
HashSet | 是 | 否 | 否 | 否 |
TreeSet | 是 | 否 | 否 | 否 |
LinkedHashSet | 是 | 否 | 是 | 否 |
Queue
Queue在java.util包中的实现主要有以下两个:
java.util.LinkedList
java.util.PriorityQueue
Deque
定义了在Queue
两端进行insert和remove函数(addFirst/addLast),经典是实现是LinkedList
。
PriorityQueue
是从JDK1.5开始提供的新的数据结构接口,它是一种基于优先级堆的极大优先级队列(基于数组的完全二叉树)。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列(参阅 Comparable),也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException),更多内容参考《Java PriorityQueue工作原理及实现》。
是否容许空 | 是否容许重复 | 是否有序(遍历输出保持插入顺序) | 是否线程安全 | |
---|---|---|---|---|
PriorityQueue | 否 | 是 | 否 | 否 |
遍历的时候,只保证第一个是最小值(或最大值),如:
Queue priorityQueue=new PriorityQueue();
priorityQueue.add(5);
priorityQueue.add(2);
priorityQueue.add(1);
priorityQueue.add(10);
priorityQueue.add(3);
System.out.println("");
Iterator iterator1=priorityQueue.iterator();
while (iterator1.hasNext()){
System.out.print(iterator1.next()+" ");
}
output:1 3 2 10 5
Map
Map在java.util包中的实现主要包括以下几个:
java.util.HashMap
java.util.Hashtable
java.util.EnumMap
java.util.IdentityHashMap
java.util.LinkedHashMap
java.util.Properties
java.util.TreeMap
java.util.WeakHashMap
HashMap vs TreeMap vs LinkedHashMap
我们经常使用的也就是HashMap
和TreeMap
。HashMap
线程不安全,不保证内部存储元素的任何顺序,详情参考Java HashMap工作原理及实现。TreeMap
保证了存储元素的顺序。
![](https://img.haomeiwen.com/i1212395/f9a3d99dc0b6d50d.png)
HashMap vs Hashtable
Hashtable
is synchronized, whereasHashMap
is not. This makesHashMap
better for non-threaded applications, as unsynchronized Objects typically perform better than synchronized ones.Hashtable
does not allownull
keys or values.HashMap
allows onenull
key and any number ofnull
values.- One of HashMap's subclasses is
LinkedHashMap
, so in the event that you'd want predictable iteration order (which is insertion order by default), you could easily swap out theHashMap
for aLinkedHashMap
. This wouldn't be as easy if you were usingHashtable
.
Since synchronization is not an issue for you, I'd recommendHashMap
. If synchronization becomes an issue, you may also look atConcurrentHashMap
.
Differences between HashMap and Hashtable?
是否容许空 | 是否容许重复 | 是否有序(遍历输出保持插入顺序) | 是否线程安全 | |
---|---|---|---|---|
HashMap | 是 | 是 | 否 | 否 |
HashTable | 否 | 是 | 否 | 是 |
TreeMap | 只是value容许 | 是 | 否 | 否 |
LinkedHashMap | 是 | 是 | 是 | 否 |
如果对集合的实现比较感兴趣,推荐大家读取其中链接和参考文献,最好自己打开源码读读。其中若有纰漏,欢迎指正。