HashSet、TreeSet、CopyOnWriteArraySet和CopyOnWriteArrayList

瘋狂的大寶發表於2018-10-24

HashSet

 

特點:無序/非同步/元素可以是null,但只能放入一個null/

 

當向HashSet集合中存入一個元素時,HashSet會呼叫該物件的hashCode()方法來得到該物件的hashCode值, 然後根據 hashCode值來決定該物件在HashSet中儲存位置。

 

簡單的說,HashSet集合判斷兩個元素相等的標準是兩個物件通過equals方法比較相等,並且兩個物件的hashCode()方法返回值相等。如果要把一個物件放入HashSet中,重寫該物件對應類的equals方法,也應該重寫其hashCode()方法。

 

需同時重寫equals()和hashCode(), 其規則是: 1)如果兩個物件通過equals方法比較返回true時,其hashCode也應該相同。2)另外,物件中用作equals比較標準的屬性,都應該用來計算 hashCode的值。

 

TreeSet類

特點:TreeSet 是二差樹實現的/Treeset中的資料是自動排好序的/不允許放入null值/ TreeSet中加入的應該是同一個類的物件

 

TreeSet是SortedSet介面的唯一實現類,TreeSet可以確保集合元素處於排序狀態。

支援兩種排序方式:自然排序(預設排序方式)定製排序。

 

TreeSet判斷兩個物件不相等的方式是:兩個物件通過equals方法返回false者通過CompareTo方法比較沒有返回0

比較大小規則:實現了Comparable介面(定義了一個compareTo(Object obj)方法)的物件就可以比較大小。obj1.compareTo(obj2)方法如果返回0,則說明被比較的兩個物件相等,如果返回一個正數,則表明obj1大於obj2,如果是 負數, 則表明obj1小於obj2。

 

 

自然排序:使用要排序元素的CompareTo(Object obj)方法來比較元素之間大小關係,然後將元素按照升序排列。

定製排序:應該使用Comparator介面,實現 int compare(T o1,T o2)方法。

CopyOnWriteArraySet

特點:

基於CopyOnWriteArrayList實現,執行緒安全無需集合。

add呼叫的是CopyOnWriteArraylist的addIfAbsent方法。

CopyOnWriteArraySet每次add要進行遍歷陣列,效能略低於CopyOnWriteArrayList。

適用於set大小一般很小,讀操作遠遠多於寫操作的場景。

CopyOnWriteArrayList

特點寫時複製的方法

 

當有新元素新增到CopyOnWriteArrayList時,先從原有的陣列中拷貝一份出來,然後在新的陣列做寫操作,寫完之後,再將原來的陣列引用指向到新陣列

當有新元素加入的時候,如下圖,建立新陣列,並往新陣列中加入一個新元素,這個時候,array這個引用仍然是指向原陣列的

當元素在新陣列新增成功後,將array這個引用指向新陣列。

為了避免在多執行緒併發add的時候,複製出多個副本出來,把資料搞亂了。CopyOnWriteArrayList的整個add操作都是在的保護下進行的

讀資料規則:

1、如果寫操作未完成,那麼直接讀取原陣列的資料;

2、如果寫操作完成,但是引用還未指向新陣列,那麼也是讀取原陣列資料;

3、如果寫操作完成,並且引用已經指向了新的陣列,那麼直接從新陣列中讀取資料

使用場景:

  1. 讀多寫少
  2. 不能用於實時讀的場景。像拷貝陣列、新增元素都需要時間,所以呼叫一個set操作後,讀取到資料可能還是舊的,雖然CopyOnWriteArrayList 能做到最終一致性,但是還是沒法滿足實時性要求
  3. 由於寫操作的時候,需要拷貝陣列,會消耗記憶體,如果原陣列的內容比較多的情況下,可能導致young gc或者full gc

 

設計思想:

1、讀寫分離,讀和寫分開

2、最終一致性

3、使用另外開闢空間的思路,來解決併發衝突

相關文章