java - linkedhashset用法




HashSet vs LinkedHashSet (7)

HashSet是無序的和未排序的Set。 LinkedHashSet是HashSet的有序版本.HashSet和LinkedHashSet的唯一區別是LinkedHashSet維護插入順序。 當我們遍歷一個HashSet時,順序是不可預知的,而在LinkedHashSet的情況下它是可預測的。 LinkedHashSet維護插入順序的原因是因為底層數據結構是一個雙向鍊錶。

他們有什麼區別? 我知道

LinkedHashSet是HashSet的有序版本,它在所有元素之間維護一個雙向鍊錶。 當您關心迭代次序時,請使用此類而不是HashSet。 在遍歷HashSet時,順序是不可預知的,而LinkedHashSet允許您按照插入順序遍曆元素。

但在LinkedHashSet的源代碼中,只有調用HashSet的構造函數。 那麼雙鍊錶和插入順序在哪裡?


HashSet:實際上無序。 如果你傳遞參數意味著

Set<Integer> set=new HashSet<Integer>();
for(int i=0;i<set.length;i++)
{
  SOP(set)`enter code here`
}

輸出:可能是2,1,3不可預測。 下次再次下單。

生成FIFO順序的LinkedHashSet()


LinkedHashSet的構造函數調用以下基類構造函數:

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
  map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor);
}

正如你所看到的,內部映射是一個LinkedHashMap 。 如果您查看LinkedHashMap內部,您將發現以下字段:

private transient Entry<K, V> header;

這是有問題的鍊錶。


HashSet的:

帶下劃線的數據結構是Hashtable。 不允許重複的對象。插入順序不會保留,並且基於對象的哈希碼。 空插入是可能的(只有一次)。 它實現了Serializable,Clonable但不是RandomAccess接口。 如果頻繁操作是搜索操作,則HashSet是最佳選擇。

在HashSet中不允許重複。如果用戶試圖插入重複項,那麼我們將不會收到任何編譯或運行時異常。 添加方法只返回false。

構造函數:

HashSet h = new HashSet(); 創建一個空的HashSet對象,默認初始容量為16,默認填充率(Load factor)為0.75。

HashSet h = new HashSet(int initialCapacity); 創建一個具有指定的initialCapacity的空HashSet對象,默認填充比率為0.75。

HashSet h = new HashSet(int initialCapacity,float fillRatio);

HashSet h = new HashSet(Collection c); 為給定集合創建一個等價的HashSet對象。 這個構造函數用於集合對象之間的相互轉換。

LinkedHashSet:

它是HashSet的子類。 它與HashSet完全相同,包括(構造函數和方法),除了以下差異。

差異HashSet:

  1. 帶下劃線的數據結構是Hashtable。
  2. 插入順序不會保留。
  3. 推出了1.2版本。

LinkedHashSet:

  1. 帶下劃線的數據結構是LinkedList和Hashtable的組合。
  2. 插入順序被保留。
  3. 在1.4版本中生成。

如果您查看LinkedHashSet類中調用的構造函數,您將在內部看到它是一個用於支持目的的LinkedHashMap


我建議你大部分時間使用LinkedHashSet ,因為它總體上具有更好的性能 ):

  1. 可預測的 迭代順序LinkedHashSet(Oracle)
  2. LinkedHashSet比HashSet更加昂貴;
  3. 一般來說,性能比HashMap稍好一些,因為大部分時間我們都使用Set結構進行迭代。

性能測試:

------------- TreeSet -------------
 size       add  contains   iterate
   10       746       173        89
  100       501       264        68
 1000       714       410        69
10000      1975       552        69
------------- HashSet -------------
 size       add  contains   iterate
   10       308        91        94
  100       178        75        73
 1000       216       110        72
10000       711       215       100
---------- LinkedHashSet ----------
 size       add  contains   iterate
   10       350        65        83
  100       270        74        55
 1000       303       111        54
10000      1615       256        58

您可以在這裡看到源測試頁面: 最終性能測試示例


答案在於LinkedHashSet用於構造基類的構造函數:

public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);      // <-- boolean dummy argument
}

...

public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);            // <-- boolean dummy argument
}

...

public LinkedHashSet() {
    super(16, .75f, true);                         // <-- boolean dummy argument
}

...

public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);   // <-- boolean dummy argument
    addAll(c);
}

並且描述了一個帶有布爾參數的HashSet構造函數的例子,如下所示:

/**
 * Constructs a new, empty linked hash set.  (This package private
 * constructor is only used by LinkedHashSet.) The backing
 * HashMap instance is a LinkedHashMap with the specified initial
 * capacity and the specified load factor.
 *
 * @param      initialCapacity   the initial capacity of the hash map
 * @param      loadFactor        the load factor of the hash map
 * @param      dummy             ignored (distinguishes this
 *             constructor from other int, float constructor.)
 * @throws     IllegalArgumentException if the initial capacity is less
 *             than zero, or if the load factor is nonpositive
 */
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}




linkedhashset