[Java] 多個Map的性能比較(TreeMap、HashMap、ConcurrentSkipListMap)


比較Java原生的 3種Map的效率。
1.  TreeMap
2.  HashMap
3.  ConcurrentSkipListMap

結果:

模擬150W以內海量數據的插入和查找,通過增加和查找兩方面的性能測試,結果如下:

Map類型 插入 查找(在100W數據量中)
  10W 50W 100W 150W 0-1W 0-25W 0-50W
Concurrent
SkipListMap
62 ms 227 ms 433 ms 689ms 7 ms 80 ms 119 ms
HashMap 18 ms 93 ms 217 ms 303ms 2 ms 13 ms 45 ms
TreeMap 33 ms 228 ms 429 ms 584 ms 4ms 34 ms 61 ms

分析說明

diagram

 

圖1- 1常數和logn函數效率對比示例圖(橫軸-n數據量,縱軸-f(n)時間)

TreeMap基於紅黑樹(一種自平衡二叉查找樹)實現的,時間復雜度平均能達到O(log n)。
HashMap是基於散列表實現的,時間復雜度平均能達到O(1)。
ConcurrentSkipListMap是基於跳表實現的,時間復雜度平均能達到O(log n)。

如圖所示:
當數據量增加時,HashMap會引起散列沖突,解決沖突需要多花費一些時間代價,故在f(n)=1向上浮動。
隨着數據量的增加,HashMap的時間花費小且穩定,在單線程的環境下比TreeMap和ConcurrentSkipListMap在插入和查找上有很大的優勢。

(1) TreeMap與HashMap相比較

Ø  HashMap里面存入的鍵值對在取出的時候是隨機的,它根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度。在Map 中插入、刪除和定位元素,HashMap是最好的選擇。

Ø  TreeMap取出來的是排序后的鍵值對。插入、刪除需要維護平衡會犧牲一些效率。但如果要按自然順序或自定義順序遍歷鍵,那么TreeMap會更好。

本測試增加和查找功能,HashMap比TreeMap的效率要高。

(2) TreeMapConcurrentSkipListMap相比較

Ø  Skip list(跳表)是一種可以代替平衡樹的數據結構,默認是按照Key值升序的。Skip list讓已排序的數據分布在多層鏈表中,以0-1隨機數決定一個數據的向上攀升與否,通過“空間來換取時間”的一個算法,在每個節點中增加了向前的指針,在插入、刪除、查找時可以忽略一些不可能涉及到的結點,從而提高了效率。
從概率上保持數據結構的平衡比顯示的保持數據結構平衡要簡單的多。對於大多數應用,用Skip list要比用樹算法相對簡單。由於Skip list比較簡單,實現起來會比較容易,雖然和平衡樹有着相同的時間復雜度(O(logn)),但是skip list的常數項會相對小很多。Skip list在空間上也比較節省。一個節點平均只需要1.333個指針(甚至更少)。

 

skipList

圖1-2 Skip list結構圖(以7,14,21,32,37,71,85序列為例)

Skip list的性質

(1) 由很多層結構組成,level是通過一定的概率隨機產生的。
(2) 每一層都是一個有序的鏈表,默認是升序,也可以根據創建映射時所提供的Comparator進行排序,具體取決於使用的構造方法。
(3) 最底層(Level 1)的鏈表包含所有元素。
(4) 如果一個元素出現在Level i 的鏈表中,則它在Level i 之下的鏈表也都會出現。
(5) 每個節點包含兩個指針,一個指向同一鏈表中的下一個元素,一個指向下面一層的元素。

Ø  ConcurrentSkipListMap具有Skip list的性質 ,並且適用於大規模數據的並發訪問。多個線程可以安全地並發執行插入、移除、更新和訪問操作。與其他有鎖機制的數據結構在巨大的壓力下相比有優勢。

Ø  TreeMap插入數據時平衡樹采用嚴格的旋轉(比如平衡二叉樹有左旋右旋)來保證平衡,因此Skip list比較容易實現,而且相比平衡樹有着較高的運行效率。
本測試的增加功能,ConcurrentSkipListMap和TreeMap效率相差不大。

查找功能在50W數據量以后,TreeMap更有效率,因為ConcurrentSkipListMap自帶鎖機制,會占用一些效率,但對於多線程並發的環境下,ConcurrentSkipListMap的效率會比Treep要好的。

本測試查找方法使用Map的get方法,循環、離散獲取。對於ConcurrentSkipListMap,獲得順序片段,可用subMap()方法,提取 50w的子序列只需要1ms,具有巨大優勢。 SkipListMap的范圍查詢效率比HashMap和TreeMap效率都要高。

(3) SkipList 參考資料

[1] http://stackoverflow.com/questions/256511/skip-list-vs-binary-tree
[2] http://www.cnblogs.com/xuqiang/archive/2011/05/22/2053516.html
[3] http://imtinx.iteye.com/blog/1291165


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM