Java Set Reihenfolge beibehalten?

179

Behält ein Java-Set die Reihenfolge bei? Eine Methode gibt ein Set an mich zurück und angeblich sind die Daten geordnet, aber wenn sie über das Set iterieren, sind die Daten ungeordnet. Gibt es einen besseren Weg, dies zu verwalten? Muss die Methode geändert werden, um etwas anderes als einen Satz zurückzugeben?

user840930
quelle
3
"Die Elemente werden in keiner bestimmten Reihenfolge zurückgegeben (es sei denn, dieser Satz ist eine Instanz einer Klasse, die eine Garantie bietet)." sagt die Iteratormethode für eine Menge. hier
Keyser

Antworten:

256

Die SetSchnittstelle bietet keine Bestellgarantien.

Seine Unterschnittstelle SortedSetstellt eine Menge dar, die nach einem bestimmten Kriterium sortiert ist. In Java 6 werden zwei Standardcontainer implementiert SortedSet. Sie sind TreeSetund ConcurrentSkipListSet.

Neben der SortedSetSchnittstelle gibt es auch die LinkedHashSetKlasse. Es merkt sich die Reihenfolge, in der die Elemente in die Menge eingefügt wurden, und gibt seine Elemente in dieser Reihenfolge zurück.

NPE
quelle
21
Aufgrund des unterschiedlichen String-Hashings in Java 8 ändert sich außerdem die Standardreihenfolge (unsortiert) in Sets und Maps. Wenn Sie sich auf unsortierte Bestellungen verlassen, verhält sich Ihr Code unter Java 8 anders.
Rustyx
Ich verstehe, dass die Klasse, die nicht bestellt, normal ist, aber das Verhalten, das ich erwartet hatte, war, sie so zu belassen, wie sie eingeführt wurden, und nicht mit der Reihenfolge herumzuspielen, sondern nur die Elemente jedes Mal zu mischen, wenn eine aggregiert wird. Ihre Lösung ist nicht optimal verdorren, weil ich dann eine ganze Struktur implementieren muss, damit sie auf die gleiche Weise sortiert werden, wie sie eingeführt wurden: S
White_King
@White_King: Eine Menge ist ein mathematisches Konzept, das nicht den Begriff "Einfügereihenfolge" enthält. Daher ist es sinnvoll, dass die Java-Schnittstelle ihren Konventionen folgt. Es gibt geordnete Mengen, aber die Reihenfolge wird durch eine Beziehung (Komparator in Java) angegeben, die wiederum die Definition in der Mengenlehre mit der Definition in Java übereinstimmt. Ihre Erwartung, dass die Einfügereihenfolge beibehalten wird, stammt wahrscheinlich aus Listen, aber Sätze sind keine Listen.
Konrad Höffner
103

LinkedHashSet ist das, was Sie brauchen.

xiaofeng.li
quelle
43
A Listist kein a Set(es garantiert keine Eindeutigkeit der Mitgliedschaft).
Begrenzte Versöhnung
10
In vielen geschäftlichen Einzelfällen kann List nicht nur zum Beibehalten der Bestellung anstelle von Set verwendet werden. LinkedHashSet verwaltet die Reihenfolge und speichert Unikate.
Gubs
18

Wie viele der Mitglieder vorgeschlagen haben, verwenden Sie LinkedHashSet , um die Reihenfolge der Sammlung beizubehalten. Mit dieser Implementierung können Sie Ihr Set verpacken.

Die SortedSet- Implementierung kann für die sortierte Reihenfolge verwendet werden, verwenden Sie jedoch für Ihren Zweck LinkedHashSet .

Auch aus den Dokumenten,

"Diese Implementierung erspart ihren Kunden die nicht spezifizierte, im Allgemeinen chaotische Reihenfolge, die von HashSet bereitgestellt wird, ohne die mit TreeSet verbundenen erhöhten Kosten zu verursachen. Sie kann verwendet werden, um eine Kopie eines Satzes zu erstellen, der unabhängig vom Original dieselbe Reihenfolge wie das Original hat Implementierung des Sets: "

Quelle: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

Lakshman
quelle
9

Set ist nur eine Schnittstelle. Um die Reihenfolge beizubehalten, müssen Sie eine bestimmte Implementierung dieser Schnittstelle und der Unterschnittstelle SortedSet verwenden, z. B. TreeSet oder LinkedHashSet. Sie können Ihr Set folgendermaßen verpacken:

Set myOrderedSet = new LinkedHashSet(mySet);
javatutorial
quelle
7

Hier ist eine kurze Zusammenfassung der Auftragseigenschaften der Setin Java verfügbaren Standardimplementierungen :

  1. Behalten Sie die Einfügereihenfolge bei : LinkedHashSet und CopyOnWriteArraySet (thread-sicher)
  2. Halten Sie die Elemente innerhalb des Satzes sortiert: TreeSet , EnumSet (spezifisch für Enums) und ConcurrentSkipListSet (thread-sicher)
  3. hält die Elemente nicht in einer bestimmten Reihenfolge: HashSet (das, das Sie versucht haben)

Für Ihren speziellen Fall können Sie entweder zuerst die Elemente sortieren und dann eine von 1 oder 2 verwenden (höchstwahrscheinlich LinkedHashSetoder TreeSet). Alternativ oder effizienter können Sie einfach unsortierte Daten zu einem hinzufügen, TreeSetdas die Sortierung automatisch für Sie übernimmt.

Assylien
quelle
7

Um die Bestellung beizubehalten, verwenden Sie Listoder a LinkedHashSet.

JHS
quelle
1
Es ist LinkedHashSetnicht ... Map.
Marko Topolnik
Ich brauche ein Set, keine Liste, ich brauche ein Set, das AUCH die Reihenfolge der Injektion der Objekte beibehält, die ich denke
White_King
5

Ein LinkedHashSet ist eine geordnete Version von HashSet, die eine doppelt verknüpfte Liste über alle Elemente hinweg verwaltet. Verwenden Sie diese Klasse anstelle von HashSet, wenn Sie sich für die Iterationsreihenfolge interessieren.

Danail Tsvetanov
quelle
3

Aus dem Javadoc für Set.iterator():

Gibt einen Iterator über die Elemente in diesem Satz zurück. Die Elemente werden in keiner bestimmten Reihenfolge zurückgegeben (es sei denn, dieser Satz ist eine Instanz einer Klasse, die eine Garantie bietet).

Und wie bereits von Shuuchan festgestellt , TreeSetist a eine Implementierung Set, die eine garantierte Reihenfolge hat:

Die Elemente werden in ihrer natürlichen Reihenfolge oder von einem zum festgelegten Erstellungszeitpunkt bereitgestellten Komparator geordnet, je nachdem, welcher Konstruktor verwendet wird.

hmjd
quelle
3

Normalerweise behält set die Reihenfolge nicht bei, wie z. B. HashSet, um schnell ein Emelent zu finden. Sie können jedoch versuchen, LinkedHashSet zu verwenden, damit die von Ihnen eingegebene Reihenfolge beibehalten wird.

user1335794
quelle
1

Es gibt 2 verschiedene Dinge.

  1. Sortieren Sie die Elemente in einer Menge. Für die wir SortedSet und ähnliche Implementierungen haben.
  2. Pflegen Sie die Einfügereihenfolge in einem Satz. Für welche LinkedHashSet und CopyOnWriteArraySet (thread-safe) verwendet werden können.
Aruna
quelle
0

Die Set-Schnittstelle selbst legt keine bestimmte Reihenfolge fest. Das SortedSet tut dies jedoch.

Jens Borgland
quelle
-2

Nur SortedSetkann die Bestellung derSet


quelle
Die Frage ist, die Einfügereihenfolge beizubehalten (die zufällig sortiert ist).
Assylias