6
votes

Pourquoi la classe hashset a déjà trié quand j'utilise l'itérateur?

J'ai le code suivant sur ma méthode principale code> principale et lorsque je ithétiez via le fichier définir code> et imprimez les valeurs, les valeurs sont déjà triées. Quelle est la raison? XXX PRE>

Sortie: P>

2
3
6
7
9


2 commentaires

Vous pouvez essayer d'ajouter les chiffres dans un ordre différent et de voir si la sortie reste la même. Mais comme les réponses disent, il n'y a aucune garantie sur la commande, et c'est donc juste une coïncidence :)


Contrairement à la beaucoup de réponses actuelles, ce n'est pas vraiment un accident ni une coïncidence; Mais vous trouverez que cela ne se produira pas généralement si vous mettez des nombres plus gros dans l'ensemble, ou un mélange de nombres négatifs et positifs.


3 Réponses :


4
votes

6 commentaires

Ce n'est pas un coïncidence. C'est une question de hashcode implémentation dans entier .


@Niematojaktomasz hashset exécute un hachage supplémentaire pour distribuer le dans la quantité limitée de godets qu'il maintient. Cette mise en œuvre est abstraite, c'est pourquoi je dis que c'est une coïncidence.


@Niematojaktomasz: C'est une coïncidence. La brise de hachage effectuée dans hashset s interne, par exemple (généralement) ruine la commande d'entiers.


Merci les gars. Donc, si j'ai un ensemble d'une classe que j'ai créée, quand je vais itérer à travers l'ensemble. Les articles seront-ils triés par le hashcode?


@Louiswasserman, @sotiriosdelimanolis Je conviens que cela ne devrait pas être quelque chose que vous devez dépendre de la mise en œuvre de la mise en œuvre. Et cela ne fonctionnera pas pour aucun ensemble d'entiers. Mais l'effet résulte du loadfactor, de la capacité de la matrice sous-jacente efficace et que tous les éléments sont des entiers positifs plus petits que la capacité. Pas clairement de coïncidence. J'ai remarqué que hashmap utilise un tel truc (h = key.hascode ()) ^ (H >>> 16) , mais cela n'affecte pas les petites valeurs.


@Mariagabriela: généralement pas. Vous ne devriez pas dépendre de ce comportement, surtout étant donné qu'il est autorisé à changer entre les versions Java.




4
votes

Je ne suis pas sûr de l'appeler une coïncidence est la bonne réponse. Il n'y a aucune chance impliquée. Il résulte des fonctions de hachage utilisées, les petites valeurs que vous mettez dans le hashset et la petite quantité d'éléments que vous avez mis dans l'ensemble.

  • pour entier, hashcode () est la valeur INT de l'entier.

  • hashmap (and hashset) fait un hachage supplémentaire sur la valeur renvoyée par hashcode , mais ce hachage supplémentaire ne modifie pas la valeur pour ces petits nombres que vous avez ajouté au hashSet.

  • Enfin, le godet que chaque entier est mis en est le mot modulu de code de hachage modifié la capacité du hashset. La capacité initiale d'un hashset / hachemap est de 16.

  • Par conséquent, 2 est ajouté au godet 2, 7 est ajouté au godet 7, etc ...

  • Lorsque vous ithétez sur les éléments du hashset, les godets sont visités dans l'ordre et, étant donné que chaque godet dispose d'un seul élément, vous obtenez les chiffres triés.

    Voici comment le godet est calculé: xxx

    Par conséquent, les godets de 2,7,3,9,6 sont 2,7,3 , 9,6 respectivement.

    L'amélioration de la boucle que vous utilisez pour itérer sur le hashset visit les godets dans l'ordre et que, pour chaque godet itière sur ses entrées (qui sont stockées dans une liste liée). Par conséquent, pour votre entrée, 2 est visitée en premier, suivi de 3, 6, 7 et 9.

    Si vous ajoutez des chiffres supérieurs à 15, la méthode hachage et le < Code> Index pour Méthode (en supposant que vous ne modifiez pas la capacité par défaut du hashset) empêcherait les chiffres d'être triés lors de l'itération par l'itérateur HASHSET.


2 commentaires

Bonne information, +1. Vous avez donné du code de l'algorithme de hachage JDK 6. Fait intéressant, même si le calcul du seau change de JDK 6 à 7 à 8, les godets des entiers 0 à 15 restent les mêmes. Cependant, le godet calculé sera différer dans Java 8 de celle de Java 6 et 7 pour les entiers 16 et plus.


@RGettman Je viens de googler le code et j'ai eu l'algorithme JDK 6.