164 votes

HashSet vs LinkedHashSet

Quelle est la différence entre eux ? Je sais que

Un LinkedHashSet est une version ordonnée de HashSet qui maintient une liste doublement liée sur tous les éléments. Utilisez cette classe à la place de HashSet lorsque vous vous souciez de l'ordre d'itération. Lorsque vous itérez à travers un HashSet, l'ordre l'ordre est imprévisible, tandis qu'un LinkedHashSet vous permet d'itérer à travers les éléments dans l'ordre dans lequel ils sont présentés. dans l'ordre dans lequel ils ont été insérés.

Mais dans le code source de LinkedHashSet, on appelle seulement les constructeurs de HashSet. Alors où est la liste doublement liée et l'ordre d'insertion ?

2 votes

Utilisez l'option Intellij(Ctrl + B) pour trouver la réponse. :)

0 votes

Bien sûr, vous avez besoin du code source joint :)

67voto

aioobe Points 158466

La différence entre les deux est, comme vous l'avez dit :

A LinkedHashSet est une version ordonnée de HashSet qui maintient une liste doublement liée à tous les éléments. Utilisez cette classe à la place de HashSet lorsque vous vous souciez de l'ordre d'itération. Lorsque vous itérez dans un HashSet l'ordre est imprévisible, tandis qu'une LinkedHashSet vous permet d'itérer à travers les éléments dans l'ordre dans lequel ils ont été insérés.

Quant à votre question :

Mais dans le code source de LinkedHashSet, il n'y a que des appels aux constructeurs de HashSet.

La réponse se trouve dans quels constructeurs le site LinkedHashSet utilise pour construire la classe de base :

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);
}

Et (un exemple de) HashSet qui prend un argument booléen est décrit, et ressemble à ceci :

/**
 * 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 votes

Une classe parent ayant une fonctionnalité explicitement pour une classe enfant, un argument ignoré pour distinguer

5 votes

Ce n'est pas exactement une conception propre qui utilise un paramètre fictif pour la désambiguïsation du constructeur.

8 votes

C'est une conception raisonnablement propre, parce que l'API est propre (le constructeur de ce HashSet est un package privé). Les détails de l'implémentation n'ont pas d'importance pour les utilisateurs de la classe. La maintenance de ce code pourrait être plus difficile, mais dans le cas des classes java.util, même de très petites améliorations des performances peuvent le justifier.

25voto

NPE Points 169956

LinkedHashSet Les constructeurs de l'entreprise invoquent le constructeur de la classe de base suivant :

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

Comme vous pouvez le voir, la carte interne est une LinkedHashMap . Si vous regardez à l'intérieur LinkedHashMap vous découvrirez le champ suivant :

private transient Entry<K, V> header;

Voici la liste liée en question.

9voto

ColinD Points 48573

Vous devriez regarder la source de la HashSet le constructeur qu'il appelle... c'est un constructeur spécial qui rend la sauvegarde Map a LinkedHashMap au lieu d'un simple HashMap .

0 votes

Merci, dans HashSet il y a un constructeur pour créer LinkedHashMap, qui est appelé dans LinkedHashSet et toute la logique est dans LinkedHashMap.

3voto

Justin Points 9

HashSet : Unordered en fait. si u passe le paramètre signifie

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

Out Put : Peut être 2,1,3 pas prévisible. la prochaine fois, une autre commande.

LinkedHashSet() qui produisent un ordre FIFO.

1voto

reef Points 926

Si vous jetez un coup d'œil aux constructeurs appelés à partir de l'interface de l'entreprise. LinkedHashSet vous verrez qu'en interne, c'est une classe LinkedHashMap qui est utilisé à des fins de soutien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X