Ordonarea elementelor în Java HashSet (Programare, Java, Colecții, Hashset, Linkedhashset)

Sam Adamsh a intrebat.

De ce al doilea și al treilea set păstrează ordinea:

Integer[] j = new Integer[]{3,4,5,6,7,8,9};
LinkedHashSet<Integer> i = new LinkedHashSet<Integer>();
Collections.addAll(i,j);
System.out.println(i); 

HashSet<Integer> hi = new HashSet<Integer>(i);
System.out.println(hi); 

LinkedHashSet<Integer> o = new LinkedHashSet<Integer>(hi);
System.out.println(o); 

Iată rezultatul pe care îl obțin:

3,4,5,6,7,8,9
3,4,5,6,7,8,9
3,4,5,6,7,8,9

user3133925

Comentarii

  • stackoverflow.com/a/2704640/1048330 –  > Por tenorsax.
  • În general, , Hărțile (sau seturile) implementate folosind hashing nu au o ordine bine definită. (Deși unele implementări, de exemplu LinkedHashSet, au o ordine ca și adăugată; consultați documentația [class-level] pentru garanții, dacă există. Comportamentul este discutat atât în documentația HashSet, cât și în cea a LinkedHashSet). – user166390
  • Behrang are dreptate când spune că este o coincidență. În principal, din faptul că codurile hash întregi păstrează ordinea. Încercați să adăugați mai multe numere, precum și numere mai mari la setul hash și vedeți dacă ordinea elementelor este păstrată. –  > Por Brent Worden.
2 răspunsuri
βξhrαng

Cea de-a doua (folosind doar HashSet) este doar o coincidență. Din JavaDocs:

Această clasă implementează interfața Set, susținută de un tabel hash (de fapt, o instanță HashMap). Nu oferă nicio garanție în ceea ce privește ordinea de iterație a setului; în special, nu garantează că ordinea va rămâne constantă în timp.. Această clasă permite elementul null.

Cea de-a treia clasă (LinkedHashSet) este concepută pentru a fi astfel:

Implementarea tabelei Hash și a listei legate a interfeței Set, cu o ordine de iterație previzibilă. Această implementare diferă de HashSet prin faptul că menține o listă dublu-legată care trece prin toate intrările sale. Această listă legată definește ordinea de iterație, care este ordinea în care elementele au fost inserate în set (ordinea de inserție). Rețineți că ordinea de inserție nu este afectată în cazul în care un element este reintrodus în set. (Un element e este reintrodus într-un set s dacă s.add(e) este invocat atunci când s.contains(e) ar fi returnat true imediat înainte de invocare).

Gray

Răspunsul lui @Behrang este bun, dar, pentru a fi mai specific, singurul motiv pentru care HashSet pare să fie în aceeași ordine ca și LinkedHashSet este că integer.hashCode() se întâmplă să fie valoarea întreagă în sine, astfel încât numerele se întâmplă să fie în ordinea în HashSet stocare internă. Aceasta este extrem de mult specific implementării și, așa cum spune @Behrang, este o coincidență.

De exemplu, dacă utilizați new HashSet<>(4) care setează numărul inițial de găleți la 4 (în loc de 16), atunci ați fi putut obține următoarea ieșire:

HashSet<Integer> hi = new HashSet<Integer>(4);
...
[3, 4, 5, 6, 7, 8, 9]
[8, 9, 3, 4, 5, 6, 7]
[8, 9, 3, 4, 5, 6, 7]

Dacă ați fi blocat în values >= 16, ați fi putut obține ceva de genul acesta:

Integer[] j = new Integer[] { 3, 4, 5, 6, 7, 8, 9, 16 };
...
[3, 4, 5, 6, 7, 8, 9, 16]
[16, 3, 4, 5, 6, 7, 8, 9]
[16, 3, 4, 5, 6, 7, 8, 9]