圖學java基礎篇之集合

文章轉載自:http://www.cnblogs.com/good-temper/p/4907745.html


(本文部分圖片引用自其他博客,最後有鏈接,侵刪。由於筆記使用markdown記錄,格式可能不是太好看,見諒)

集合結構


紅字爲java.util包下的,綠字爲concurrent包下擴展的與併發相關的類

List

ArrayList

功能:有序非線程安全列表
要點:

  • 底層存儲用Object數組
  • 元素可爲null
  • 自動擴容至1.5倍
  • 適合隨機訪問,不適合大量或頻繁增刪
LinkedList

功能:有序非線程安全列表
要點:

  • 基於雙向鏈表實現
  • 元素可爲null
  • 同時實現了雙端隊列Deque,支持隊列、堆棧操作
  • 適合增刪,順序訪問,不適合隨機訪問
Vector

功能:有序線程安全列表
要點:

  • 功能和ArrayList一樣,只有線程安全區別,效率較ArrayList低
  • 實際上算是老版本的List,除了線程安全的情況下不用
Stack

功能:基於Vector實現的堆棧
要點:

  • 線程安全
  • 後進先出(LIFO)1
CopyOnWriteArrayList

功能:快照版本的ArrayList,修改操作通過複製一份數組操作
要點:

  • 線程安全
  • 任何修改都會在拷貝的新副本上進行
  • 修改操作通過ReentrantLock同步
  • 迭代器只能訪問,不能修改,且不會因爲遍歷過程中修改而拋異常
實現線程安全List的方法
  • 使用synchronized:對List操作是進行同步,需要自己控制
  • 使用Vector:效率低,已經較少使用了
  • 使用CopyOnWriteArrayList,前邊已經介紹了,這個只能在量小讀多寫少的場景下用,且性能很差,一般不要用
  • 使用Collections.synchronizedList():工具類提供的一個比較簡便的方法,可以直接創建一個線程安全的list,建議使用。其原理是對ArrayList進行包裝,通過一個對象鎖來控制併發,需要注意的是要弄清楚對象鎖鎖的是哪個對象。

Map

HashMap

功能:
要點:key-value的map,存儲位置根據key的hash值確定

  • 非線程安全
  • 底層使用Entry數組table
  • 衝突使用鏈存儲
  • table長度爲2^n,這樣結合hash算法有利於均勻分佈
  • 當發生衝突時,新元素會插入到鏈首
  • 每次table容量變化時,需要重新rehash
  • 鍵值均可爲null
HashTable

功能:key-value的map,存儲位置根據key的hash值確定,與Hash的算法不同之處是,其位置直接通過hash(key)%table.length計算(HashMap使用h&(length – 1)計算,效率更高,才外還有一些細節不同,可自行參看源碼)
要點:

  • 線程安全
  • 繼承自Dictionary
  • 底層使用Entry數組table
  • 衝突使用鏈存儲
  • table長度爲2^n,這樣結合hash算法有利於均勻分佈
  • 當發生衝突時,新元素會插入到鏈首
  • 每次table容量變化時,需要重新rehash
  • 鍵值不能爲空
TreeMap

功能:基於紅黑樹實現的有序集合 要點:

  • 非線程安全
  • 底層爲一個棵紅黑樹
  • 繼承NavigableMap,主要實現了SortMap,因此是有序的
  • 增刪改查都可參考紅黑樹操作
ConcurrentHashMap

功能:線程安全的HashMap,屬於java.util.concurrent下的拓展類
要點:

  • 線程安全
  • 底層實現是一個Segment數組,Segment內部通過一個HashEntry數組存儲元素數據,同時Segment繼承了ReentrantLock,直接通過本身的鎖對改段數據操作同步
  • 從底層結構可以發現,其修改時不會對整個集合加鎖,而是對段加鎖,因此允許同時修改多個段,效率更高
  • 繼承NavigableMap,主要實現了SortMap,因此是有序的
  • Segment的劃分是通過key的hashCode計算
ConcurrentSkipListMap

功能:線程安全的有序Map,是通過一個叫做跳錶的數據結構實現 要點:

  • 線程安全
  • 底層實現是一個多層鏈表,每層元素都有序,每低一層都包含上一層的元素,最底層包含所有元素。這樣設計的巧妙之處是從上層逐層查找時,能夠快速定位元素區間。思想上有點像折半查找,不過是把每次折半的中間值分層存了起來。同時鏈表結構是修改操作同樣高效
  • key是有序的
  • 空間換時間,效率很高,但是空間佔用也很厲害
Map的用法
  • 非線程安全情景基本上都用HashMap
  • 有序用TreeMap
  • 線程安全優先ConcurrentHashMap
  • ConcurrentHashMap和ConcurrentSkipListMap的優劣主要在於併發量,併發量不高時前者效率高,併發量很大時可以考慮後者

Set

HashSet

功能: 就是一個value均爲同一個PRESENT對象的HashMap 要點:

  • 非線程安全
  • 底層爲一個HashMap,其所有元素value值是一個Object類型的靜態常量
  • 其他參考HashMap
TreeSet

功能: 同TreeMap 要點:

  • 非線程安全
  • 底層爲一個TreeMap,其所有元素value值是一個Object類型的靜態常量
  • 其他參考TreeMap
ConcurrentSkipListSet

功能: 同ConcurrentSkipListMap

CopyOnWriteArraySet

功能: 同ConcurrentSkipListMap
要點:

  • 需要注意的是底層實現是通過CopyOnWriteArrayList,而非HashMap
  • 使用場景與CopyOnWriteArrayList一樣

Queue

Queue實現了隊列操作,是基本集合的一個擴充,特點是提供了隊列操作offer、poll和peek,主要分爲兩類,一類只支持單端操作,常見的如PriorityQueue,另一類爲雙端隊列,可實現堆棧操作,均實現Deque。需注意的是隊列也提供了add和remove,但應避免使用。

PriorityQueue

功能:如其名,優先級隊列,可根據Comparator實現優先級排列
要點:

  • 非線程安全
  • 底層爲一個Object數組
  • 不提供Comparator時按照元素自然順序
ArrayDeque

功能:如其名,優先級隊列,可根據Comparator實現優先級排列
要點:

  • 非線程安全
  • 底層爲一個E[]數組,同時提供head和tail記錄存儲數據的首位位置
  • 由於使用數組不是鏈表,速度比LinkedList更快
LinkedBlockingDeque

功能:阻塞隊列,支持支持FIFO和FILO
要點:

  • 線程安全
  • 底層爲一個鏈表,通過一個ReentrantLock鎖控制併發
  • 可指定容量,實現阻塞,隊滿時插入阻塞,隊空時讀取阻塞,不指定則取最大整數
  • 注意take在空時不阻塞直接返回失敗,而poll則會阻塞
  • 可指定元素超時時間
LinkedBlockingQueue

功能:阻塞隊列,和LinkedBlockingDeque基本一樣,不過支持隊列操作

PriorityBlockingQueue

功能:優先級阻塞隊列,直接看名字,不解釋了

SynchronousQueue

功能:阻塞隊列,特殊之處在於其不存儲元素,一個元素入隊之後必須出隊,否則阻塞,可以理解爲1個元素的阻塞隊列

LinkedTransferQueue

功能:LinkedBlockingQueue和SynchronousQueue的結合體,特點是如果一個元素入隊過程中發現又出隊請求,則直接返回,不會再插入鏈表中 要點:

  • 注意其併發並非通過ReentrantLock,而是通過LockSupport工具類實現
DelayQueue

功能:延遲隊列,只有達到指定時間的元素才能出隊
要點:

  • 底層實現是一個PriorityQueue,通過ReentrantLock控制併發
  • 可以理解爲一個以入隊時間-延遲時間爲優先級的隊列

一些使用上的淺見

  • 從上邊的總結可以看出來java對於集合的實現非常完善,幾乎所有場景都有對應的類。因此我們應該避免重複造輪子,在合適的場景下使用合適的集合不僅省力,而且更可靠
  • 能簡則不繁,其實多數情況下我們使用基本的幾個類就夠了,複雜的實現一般用於底層框架(如JDK以及一些常用框架中就用到了不少併發的實現,但其場景都十分鮮明)。如果平時寫也想上層邏輯時使用了負責的集合類,往往我們需要認真考慮下真的有沒有必要,或者這部分是不是可以抽象爲一個通用的組件,這算是個很有用的代碼架構技巧吧。
  • 無論怎麼用,理解至上。幾個基本類之所以用的順手是因爲我們熟悉其特性,而對於複雜的集合類一定要理解其特性,否則很容易踩坑。集合部分算是JDK中最容易理解的代碼了,花一會兒時間而保證優質代碼還是很值的。

備註

一些參考博客 (都是很優秀的博客,若個人看源碼吃力,可以參考着這些博客來看)
http://cmsblogs.com/?cat=5
http://my.oschina.net/lifany/blog/191294
http://blog.csdn.net/guangcigeyun/article/details/8278349
http://www.cnblogs.com/skywang12345/p/3503480.html
http://www.infoq.com/cn/articles/java-blocking-queue/
http://my.oschina.net/readjava/blog/282882
http://hyxw5890.iteye.com/blog/1578597

以上xmind圖源文件以及該系列相關文件都將同步至github,敬請關注


發佈了26 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章