Czy zestaw Java zachowuje porządek?

179

Czy zestaw Java zachowuje kolejność? Metoda zwraca do mnie zestaw i przypuszczalnie dane są uporządkowane, ale iterując po zestawie, dane są nieuporządkowane. Czy jest lepszy sposób, aby to zrobić? Czy należy zmienić metodę, aby zwrócić coś innego niż zestaw?

user840930
źródło
3
„Elementy są zwracane w dowolnej kolejności (chyba że ten zestaw jest instancją jakiejś klasy, która daje gwarancję)”. tak mówi metoda iteratora dla zbioru. znalezione tutaj
keyser

Odpowiedzi:

256

SetInterfejs nie udziela żadnych gwarancji zamówieniu.

Jego interfejs podrzędny SortedSetreprezentuje zestaw posortowany według pewnego kryterium. W Javie 6 są dwa standardowe kontenery, które implementują SortedSet. Są TreeSeti ConcurrentSkipListSet.

Oprócz SortedSetinterfejsu jest też LinkedHashSetklasa. Zapamiętuje kolejność, w jakiej elementy zostały wstawione do zestawu i zwraca jego elementy w tej kolejności.

NPE
źródło
21
Co więcej, ze względu na różne haszowanie ciągów znaków w Javie 8, zmieni się domyślna (nieposortowana) kolejność w zestawach i mapach. Jeśli polegasz na niesortowanych zamówieniach, Twój kod będzie zachowywał się inaczej w Javie 8.
rustyx
Rozumiem, że klasa nie uporządkowana jest normalna, ale zachowanie, którego się spodziewałem, polegało na pozostawieniu ich w takiej postaci, w jakiej zostały wprowadzone, i nie zepsuciu kolejności, zamiast tego polega na tasowaniu elementów za każdym razem, gdy jeden jest agregowany. Twoje rozwiązanie nie jest optymalne, ponieważ wtedy będę musiał zaimplementować całą strukturę, aby zostały posortowane W TAKI SPOSÓB, w jaki zostały wprowadzone: S
White_King
@White_King: Zestaw jest matematyczną koncepcją, która nie zawiera pojęcia „kolejność wstawiania”, więc sensowne jest, aby interfejs Java działał zgodnie z jego konwencjami. Istnieją uporządkowane zbiory, ale kolejność jest określona przez relację (komparator w Javie), ponownie dopasowując definicję w teorii mnogości do definicji w Javie. Twoje oczekiwanie, że utrzyma kolejność reklam, prawdopodobnie pochodzi z list, ale zestawy nie są listami.
Konrad Höffner
103

LinkedHashSet jest tym, czego potrzebujesz.

xiaofeng.li
źródło
43
A Listnie jest Set(nie gwarantuje to niepowtarzalności członkostwa).
Limited Atonement
10
W wielu wyjątkowych sytuacjach biznesowych Lista nie może być używana tylko do zachowania porządku zamiast Set. LinkedHashSet utrzymuje porządek i przechowuje unikalne.
gubs
18

Jak wielu członków sugerowało, użyj LinkedHashSet, aby zachować kolejność kolekcji. Możesz opakować swój zestaw za pomocą tej implementacji.

Implementacja SortedSet może służyć do sortowania kolejności, ale w tym celu użyj LinkedHashSet .

Również z dokumentacji,

„Ta implementacja oszczędza klientom nieokreślonego, generalnie chaotycznego porządkowania zapewnianego przez HashSet, bez ponoszenia zwiększonych kosztów związanych z TreeSet. Może być wykorzystana do stworzenia kopii zestawu, który ma taką samą kolejność jak oryginał, niezależnie od oryginału wykonanie zestawu: „

Źródło: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

Lakshman
źródło
9

Zestaw to tylko interfejs. Aby zachować porządek, musisz użyć określonej implementacji tego interfejsu i podinterfejsu SortedSet, na przykład TreeSet lub LinkedHashSet. Możesz opakować swój zestaw w ten sposób:

Set myOrderedSet = new LinkedHashSet(mySet);
javatutorial
źródło
7

Oto krótkie podsumowanie charakterystyki kolejności standardowych Setimplementacji dostępnych w Javie:

  1. zachowaj kolejność reklamową : LinkedHashSet i CopyOnWriteArraySet (bezpieczne wątkowo )
  2. utrzymuj elementy posortowane w zestawie: TreeSet , EnumSet (specyficzne dla wyliczeń ) i ConcurrentSkipListSet (bezpieczne wątkowo )
  3. nie utrzymuje pozycji w określonej kolejności: HashSet (ten, którego próbowałeś)

W swoim konkretnym przypadku możesz najpierw posortować elementy, a następnie użyć jednego z 1 lub 2 (najprawdopodobniej LinkedHashSetlub TreeSet). Lub alternatywnie i wydajniej , możesz po prostu dodać nieposortowane dane do pliku, TreeSetktóry automatycznie zajmie się sortowaniem.

asylias
źródło
7

Aby zachować zamówienie, użyj Listlub a LinkedHashSet.

JHS
źródło
1
To LinkedHashSetnie ... Map.
Marko Topolnik
Potrzebuję zestawu, a nie listy, potrzebuję zestawu, który RÓWNIEŻ zachowuje kolejność wstrzykiwania obiektów, jak sądzę
White_King
5

LinkedHashSet to uporządkowana wersja HashSet, która utrzymuje podwójnie połączoną listę wszystkich elementów. Użyj tej klasy zamiast HashSet, jeśli zależy Ci na kolejności iteracji.

Danail Tsvetanov
źródło
3

Z javadoc dla Set.iterator():

Zwraca iterator dla elementów w tym zestawie. Elementy są zwracane w dowolnej kolejności (chyba że ten zestaw jest instancją jakiejś klasy, która daje gwarancję).

I, jak już powiedział shuuchan , a TreeSetjest implementacją, Setktóra ma gwarantowaną kolejność:

Elementy są porządkowane przy użyciu ich naturalnego porządku lub przez Komparator dostarczany w określonym czasie tworzenia, w zależności od używanego konstruktora.

hmjd
źródło
3

Zwykle set nie zachowuje kolejności, takiej jak HashSet, aby szybko znaleźć emelent, ale możesz wypróbować LinkedHashSet, który zachowa kolejność, którą złożyłeś.

user1335794
źródło
1

Są 2 różne rzeczy.

  1. Posortuj elementy w zestawie. Dla których mamy SortedSet i podobne implementacje.
  2. Zachowaj kolejność reklam w zestawie. W przypadku których można użyć LinkedHashSet i CopyOnWriteArraySet (bezpieczne wątkowo).
Aruna
źródło
0

Sam interfejs Set nie określa żadnej konkretnej kolejności. Jednak SortedSet .

Jens Borgland
źródło
-2

Tylko SortedSetmoże zrobić porządek zSet


źródło
Pytanie dotyczy zachowania zamówienia reklamowego (które jest posortowane).
assylias