Java集合的總結
參考博客:
http://www.jianshu.com/p/63e76826e852
http://www.cnblogs.com/LittleHann/p/3690187.html
https://github.com/pzxwhc/MineKnowContainer/issues/18
參數書籍
《java編程思想》 第十一章
一張圖說明java集合類的組織關系 其中加粗的為常用集合類
從上面的集合框架圖可以看到,Java集合框架主要包括兩種類型的容器,一種是集合(Collection),存儲一個元素集合,另一種是圖(Map),存儲鍵/值對映射。 Collection接口又有3種子類型,List、Set和Queue,再下面是一些抽象類,最後是具體實現類,常用的有ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap等等。
一:List集合
List 接口是Collection 接口的一個子類,在Collection 基礎上擴充了方法。同時可以對每個元素插入的位置進行精確的控制,它的主要實現類有 ArrayList,Vector,LinkedList。
1.1 ArrayList
ArrayList 實現了 List 接口,意味著可以插入空值,也可以插入重復的值,非同步 ,它是 基於數組 的一個實現。從源碼中的 DEFAULT_CAPACITY = 10 看出,其默認分配帶下是長度為10的數組
ArrayList 不適合 增刪操作非常多的操作, 首先可以看到這句話: elementData = Arrays.copyOf(elementData, newCapacity);
System.arraycopy(elementData, index, elementData, index + 1, size - index);
也是非常低效的。
分析了低效出現的原因,那麽我們就可以知道:如果我們需要經常進行特定位置的增刪操作,那麽最好還是不要用這個了,但是,如果我們基本上沒有固定位置的增刪操作,最好是要預估數據量的大小,然後再初始化最小容量,這樣可以有效的避免擴容。如下代碼:
ArrayList<Integer> arrayList = new ArrayList<Integer>(20);
ArrayList總結:
- ArrayList 可以插入空值,也可以插入重復值
- ArrayList 是基於數組的時候,所以很多數組的特性也直接應用到了 ArrayList。
- ArrayList 的性能消耗主要來源於擴容和固定位置的增刪。
- ArrayList 創建的時候 需要考慮是否要初始化最小容量,以此避免擴容帶來的消耗。
- ArrayList不適合做 插入和刪除操作
- ArrayList 不是線程安全的
1.2 Vector
也是實現了 List 接口,所以也是 可以插入空值,可以插入重復的值。 它和 HashTable 一樣,是屬於一種同步容器,而不是一種並發容器。(參考《Java並發編程實戰》,類似CopyOnWriteArrayList,ConcurrentHashMap這種就屬於並發容器)
內部成員變量:
protected Object[] elementData;
public Vector() {
this(10);
}
可以看到,也是基於 數組的實現,初始化也是 10 個容量。 那麽,再來看看 add()方法是否和 ArrayList 相同。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
可以看到,和 ArrayList 也是一樣的,只是加了 synchronized 進行同步, 其實很多其他方法都是通過加 synchronized 來實現同步。
Vector總結:
- 可以插入空值,也可以插入重復值
- 也是基於數組的時候,所以很多數組的特性也直接應用到了 Vector。
- 性能消耗也主要來源於 擴容。
- 創建的時候 需要考慮是否要初始化最小容量,以此避免擴容帶來的消耗。
- 相當於 ArrayList 的線程安全版本,實現同步的方式 是通過 synchronized。
- Vector不適合做 插入和刪除操作
1.3 LinkedList
LinkedList 實現了 List 接口,所以LinkedList 也可以放入重復的值,也可以放入空值。LinkedList不支持同步。LinkedList 不同於ArrayList 和Vector,它是使用鏈表的數據結構,不再是數組。Set接口擴展自Collection,它與List的不同之處在於,規定Set的實例不包含重復的元素。在一個規則集內,一定不存在兩個相等的元素。AbstractSet是一個實現Set接口的抽象類,Set接口有三個具體實現類,分別是散列集HashSet、鏈式散列集LinkedHashSet和樹形集TreeSet。
當進行增刪的時候,只需要改變指針,並不會像數組那樣出現整體數據的大規模移動,復制等消耗性能的操作。
在學習數據結構的時候,我們知道鏈表和數組的最大區別在於它們對元素的存儲方式的不同導致它們在對數據進行不同操作時的效率不同,ArrayList在做添加或者刪除的時候 效率要低於linkedList
但在做遍歷操作的時候,ArrayList要好於LinkedList
二:Set
set判斷兩個對象相同不是使用"=="運算符,而是根據equals方法
2.1 HashSet HashSet是Set接口的典型實現,HashSet使用HASH算法來存儲集合中的元素,因此具有良好的存取和查找性能。當向HashSet集合中存入一個元素時,HashSet會調用該對象的TreeSet擴展自AbstractSet,並實現了NavigableSet,AbstractSet擴展自AbstractCollection,樹形集是一個有序的Set,其底層是一顆樹,這樣就能從Set裏面提取一個有序序列了。 在實例化TreeSet時,我們可以給TreeSet指定一個比較器Comparator來指定樹形集中的元素順序。樹形集中提供了很多便捷的方法。
hashCode()方法來得到該對象的hashCode值,然後根據該HashCode值決定該對象在HashSet中的存儲位置。 值得主要的是,HashSet集合判斷兩個元素相等的標準是兩個對象通過equals()方法比較相等,並且兩個對象的hashCode()方法的返回值相等 2.2 LinkedHashSet LinkedHashSet集合也是根據元素的hashCode值來決定元素的存儲位置,但和HashSet不同的是,它同時使用鏈表維護元素的次序,這樣使得元素看起來是以插入的順序保存的。
當遍歷LinkedHashSet集合裏的元素時,LinkedHashSet將會按元素的添加順序來訪問集合裏的元素。 LinkedHashSet需要維護元素的插入順序,因此性能略低於HashSet的性能,但在叠代訪問Set裏的全部元素時(遍歷)將有很好的性能(鏈表很適合進行遍歷) 2.3 SortedSet 此接口主要用於排序操作,即實現此接口的子類都屬於排序的子類 2.4 TreeSet
2.5 EnumSet EnumSet是一個專門為枚舉類設計的集合類,EnumSet中所有元素都必須是指定枚舉類型的枚舉值,該枚舉類型在創建EnumSet時顯式、或隱式地指定。EnumSet的集合元素也是有序的,
它們以枚舉值在Enum類內的定義順序來決定集合元素的順序
三:Queue
ueue用於模擬"隊列"這種數據結構(先進先出 FIFO)。隊列的頭部保存著隊列中存放時間最長的元素,隊列的尾部保存著隊列中存放時間最短的元素。新元素插入(offer)到隊列的尾部,
訪問元素(poll)操作會返回隊列頭部的元素,隊列不允許隨機訪問隊列中的元素。結合生活中常見的排隊就會很好理解這個概念 3.1PriorityQueue PriorityQueue並不是一個比較標準的隊列實現,PriorityQueue保存隊列元素的順序並不是按照加入隊列的順序,而是按照隊列元素的大小進行重新排序,這點從它的類名也可以
看出來 3.2 Deque Deque接口代表一個"雙端隊列",雙端隊列可以同時從兩端來添加、刪除元素,因此Deque的實現類既可以當成隊列使用、也可以當成棧使用 3.2.1) ArrayDeque 是一個基於數組的雙端隊列,和ArrayList類似,它們的底層都采用一個動態的、可重分配的Object[]數組來存儲集合元素,當集合元素超出該數組的容量時,系統會在底層重
新分配一個Object[]數組來存儲集合元素 3.2.2) LinkedList
四:map
實現類:HashMap、Hashtable、LinkedHashMap和TreeMap
HashMap
HashMap是最常用的Map,它根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時,取得數據的順序完全是隨機的。因為鍵對象不可以重復,所以HashMap最多只允許一條記錄的鍵為Null,允許多條記錄的值為null,是非同步的。
Hashtable
Hashtable與HashMap類似,是HashMap的線程安全版,它支持線程的同步,即任一時刻只有一個線程能寫Hashtable,因此也導致了Hashtale在寫入時會比較慢,他繼承自Dictionary類,不同的是它不允許記錄的鍵或者值為null,同時效率較低。
ConcurrentHashMap
線程安全,並且鎖分離。ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的hashtable,它們有自己的鎖。只要多個修改操作發生在不同的段上,它們就可以並發進行。
LinkedHashMap
LinkedHashMap保存了記錄的插入順序,在用Iteraor遍歷LinkedHashMap時,先得到的記錄肯定是先插入的,在遍歷的時候會比HashMap慢,有HashMap的全部特性。
TreeMap
TreeMap實現了SortMap接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序(自然順序),也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。不允許key值為空,非同步的。
Java集合的總結