HashSet vs LinkedHashSet


153

У чому різниця між ними? я це знаю

LinkedHashSet - це впорядкована версія HashSet, яка підтримує подвійно пов'язаний Список для всіх елементів. Використовуйте цей клас замість HashSet, коли ви дбаєте про порядок ітерації. Коли ви повторюєте HashSet, порядок непередбачуваний, тоді як LinkedHashSet дозволяє переглядати елементи в тому порядку, в якому вони були вставлені.

Але у вихідному коді LinkedHashSet є лише конструктори, що викликають HashSet. То де ж подвійний зв'язаний Список та порядок вставки?


2
використовуйте параметр Intellij (Ctrl + B), щоб відстежити відповідь. :)
Дельта

звичайно, вам потрібен вихідний код, який додається. :)
Дельта

Відповіді:


65

Відповідь полягає в тому, що конструктори в 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);
}

2
Батьківський клас, що має чіткий функціонал для дочірнього класу, ігнорований аргумент для розрізнення
Traubenfuchs

5
Не зовсім чиста конструкція, що використовує фіктивний параметр для розрізнення конструктора.
Ерік Дж.

8
Це досить чистий дизайн, оскільки API чистий (цей конструктор HashSet пакет приватний). Деталі реалізації не мають значення для користувачів класу. Підтримувати цей код може бути складніше, але у випадку класів java.util навіть дуже невеликі покращення продуктивності можуть це виправдати.
lbalazscs

25

LinkedHashSetконструктори викликають наступного конструктора базового класу:

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

Як бачите, внутрішня карта - це LinkedHashMap. Якщо ви заглянете всередину LinkedHashMap, ви побачите таке поле:

private transient Entry<K, V> header;

Це пов'язаний список, про який йдеться.


24

HashSet є неврегульованим і несортоване Set.
LinkedHashSet - це замовлена ​​версія HashSet.

Єдина відмінність між HashSet і LinkedHashSet є те , що:
LinkedHashSet підтримує порядок вставки.

Коли ми повторюємо через HashSet , порядок є непередбачуваним, тоді як він передбачуваний у випадку LinkedHashSet .

Причина того, як LinkedHashSet підтримує порядок вставки, полягає в тому, що:
Основа використовуваної структури даних є подвійно-пов'язаним списком .


9

Ви повинні дивитися на джерело HashSetконструктора він називає ... це спеціальний конструктор , який робить підтримку замість просто .MapLinkedHashMapHashMap


Дякую, у HashSet є конструктор для створення LinkedHashMap, який називається в LinkedHashSet, а вся логіка - у LinkedHashMap
Shikarn-O

5

Я пропоную вам використовувати 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

Ви можете переглянути тестову сторінку джерела тут: Приклад підсумкового тестування продуктивності


2
Я не бачу жодного прогріву JVM перед цими «орієнтирами», тому я не ставлюся до цих даних серйозно. Детальніше
Felix S

3

HashSet: Насправді не упорядкований. якщо ти передає параметр, означає

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

Out Put: Може бути 2,1,3непередбачуваним. наступного разу чергове замовлення.

LinkedHashSet() які виробляють замовлення FIFO


3

HashSet не підтримують порядок елемента вставки,
LinkedHashSet підтримують порядок елемента вставки

Приклад

Set<String> set = ...;// using new HashSet<>() OR new LinkedHashSet<>()
set.add("2");
set.add("1");
set.add("ab");
for(String value : set){
   System.out.println(value);
}  

HashSet вихід

1
ab
2

LinkedHashSet вихід

2
1
ab

2

HashSet:

Підкреслена структура даних - Hashtable. Дублікати об’єктів не дозволені. Порядок введення не зберігається, і він заснований на хеш-коді об'єктів. Нульова вставка можлива (лише один раз). Він реалізує інтерфейс Serializable, Clonable, але не RandomAccess. HashSet найкраще вибирати, якщо частою операцією є пошукова операція.

У HashSet дублікати не дозволені. Якщо користувачі намагаються вставити копії, коли ми не отримаємо жодних винятків компіляції або виконання. метод add return повертається просто помилково.

Конструктори:

HashSet h = новий HashSet (); створює порожній HashSet-об'єкт із початковою потужністю 16 та коефіцієнтом заповнення за замовчуванням (коефіцієнт завантаження) - 0,75.

HashSet h = новий HashSet (int InitialCapacity); створює порожній HashSet об'єкт із заданим початковим потенціалом, а коефіцієнт заповнення за замовчуванням - 0,75.

HashSet h = новий HashSet (int InitialCapacity, float fillRatio);

HashSet h = новий HashSet (колекція c); створює еквівалентний HashSet об'єкт для даної колекції. Цей конструктор призначений для міжконверсії між об'єктом колекції.

LinkedHashSet:

Це дочірній клас HashSet. він точно такий же, як і HashSet (Конструктори та методи), за винятком наступних відмінностей.

Відмінності HashSet:

  1. Підкреслена структура даних - Hashtable.
  2. Порядок вставки не збереглося.
  3. представлена ​​версія 1.2.

LinkedHashSet:

  1. Підкреслена структура даних є комбінацією LinkedList та Hashtable.
  2. Порядок вставки зберігається.
  3. Представлений у версії 1.4.

1

Якщо ви подивитеся на конструктори, що викликаються з LinkedHashSetкласу, ви побачите, що всередині це використовується LinkedHashMapте, що використовується для підтримки.


0

Усі методи та конструктори однакові, але лише одна відмінність полягає в тому, що LinkedHashset буде підтримувати порядок вставки, але він не дозволить дублювати.

Хешсет не підтримує жодного порядку вставки. Це комбінація списку та набору простих :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.