HashSet против LinkedHashSet

153

В чем разница между ними? я знаю это

LinkedHashSet - это упорядоченная версия HashSet, которая поддерживает двусвязный список для всех элементов. Используйте этот класс вместо HashSet, если вам важен порядок итераций. Когда вы перебираете HashSet, порядок непредсказуем, а LinkedHashSet позволяет перебирать элементы в том порядке, в котором они были вставлены.

Но в исходном коде LinkedHashSet есть только вызывающие конструкторы HashSet. Итак, где же двойной список и порядок вставки?

Shikarn-О
источник
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);
}
aioobe
источник
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;

Это связанный список в вопросе.

NPE
источник
24

HashSet является неупорядоченным и несортированным множеством.
LinkedHashSet является заказанной версией HashSet.

Единственная разница между HashSet и LinkedHashSet заключается в том, что:
LinkedHashSet поддерживает порядок вставки.

Когда мы выполняем итерацию по HashSet , порядок непредсказуем, тогда как в случае LinkedHashSet он предсказуем .

Причина того, как LinkedHashSet поддерживает порядок вставки, заключается в следующем:
лежащая в основе используемая структура данных - Doubly-Linked-List .

Хема Ганапати
источник
9

Вы должны смотреть на источник HashSetконструктора он называет ... это специальный конструктор , который делает поддержку вместо просто .MapLinkedHashMapHashMap

ColinD
источник
Спасибо, в HashSet есть конструктор для создания LinkedHashMap, который вызывается в LinkedHashSet, а вся логика находится в
LinkedHashMap
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 перед этими «тестами», поэтому я не воспринял бы эти данные всерьез. Читать дальше
Феликс С
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 возвращает просто false.

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

HashSet h = новый HashSet (); создает пустой объект HashSet с начальной емкостью по умолчанию 16 и коэффициентом заполнения по умолчанию (коэффициент загрузки), равным 0,75.

HashSet h = новый HashSet (int initialCapacity); создает пустой объект HashSet с указанным initialCapacity и коэффициент заполнения по умолчанию составляет 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.
Umapathi
источник
1

Если вы посмотрите на конструкторы, вызываемые из LinkedHashSetкласса, вы увидите, что внутренне это - то, LinkedHashMapчто используется для целей поддержки.

риф
источник
0

Все методы и конструкторы одинаковы, но есть только одно отличие: LinkedHashset будет поддерживать порядок вставки, но не будет разрешать дублирование.

Hashset не будет поддерживать порядок вставки. Это сочетание List и Set просто :)

Ананд Мохан
источник