問題
比較Java原生的
1. TreeMap
2. HashMap
3. ConcurrentSkipListMap
3種Map的效率。
結果
類比150W以內海量資料的插入和尋找,通過增加和尋找兩方面的效能測試,結果如下:
Map類型 |
插入 |
尋找(在100W資料量中) |
|
10W |
50W |
100W |
150W |
0-1W |
0-25W |
0-50W |
ConcurrentSkipListMap |
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 |
分析說明
圖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) TreeMap與ConcurrentSkipListMap相比較
Ø Skip list(跳錶)是一種可以代替平衡樹的資料結構,預設是按照Key值升序的。Skip list讓已排序的資料分布在多層鏈表中,以0-1隨機數決定一個資料的向上攀升與否,通過“空間來換取時間”的一個演算法,在每個節點中增加了向前的指標,在插入、刪除、尋找時可以忽略一些不可能涉及到的結點,從而提高了效率。
從機率上保持資料結構的平衡比顯示的保持資料結構平衡要簡單的多。對於大多數應用,用Skip list要比用樹演算法相對簡單。由於Skip list比較簡單,實現起來會比較容易,雖然和平衡樹有著相同的時間複雜度(O(logn)),但是skip list的常數項會相對小很多。Skip list在空間上也比較節省。一個節點平均只需要1.333個指標(甚至更少)。
圖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,具有巨大優勢。 ConcurrentSkipListMap的效率比HashMap和TreeMap效率都要高。