Welche Java Collection soll ich verwenden?

127

In dieser Frage Wie kann ich einen Standardbibliothekscontainer in C ++ 11 effizient auswählen? ist ein praktisches Flussdiagramm für die Auswahl von C ++ - Sammlungen.

Ich dachte, dass dies eine nützliche Ressource für Leute ist, die sich nicht sicher sind, welche Sammlung sie verwenden sollen, deshalb habe ich versucht, ein ähnliches Flussdiagramm für Java zu finden, und konnte dies nicht.

Welche Ressourcen und "Spickzettel" stehen zur Verfügung, um die Auswahl der richtigen Sammlung für die Programmierung in Java zu erleichtern? Woher wissen die Benutzer, welche List-, Set- und Map-Implementierungen sie verwenden sollten?

Tim B.
quelle
Das Buch Java Generics and Collections (Naftalin & Wadler) enthält ein Kapitel dazu.
Christophe Roussy

Antworten:

291

Da ich kein ähnliches Flussdiagramm finden konnte, habe ich beschlossen, selbst eines zu erstellen.

Dieses Flussdiagramm behandelt nicht Dinge wie synchronisierten Zugriff, Thread-Sicherheit usw. oder die Legacy-Sammlungen, sondern die 3 Standard- Sets , 3 Standard- Karten und 2 Standard- Listen .

Geben Sie hier die Bildbeschreibung ein

Dieses Bild wurde für diese Antwort erstellt und ist unter einer Creative Commons Attribution 4.0 International License lizenziert. Die einfachste Zuordnung besteht darin, entweder auf diese Frage oder auf diese Antwort zu verlinken.

Andere Ressourcen

Die wahrscheinlich nützlichste andere Referenz ist die folgende Seite aus der Orakel-Dokumentation, die jede Sammlung beschreibt .

HashSet vs TreeSet

Es gibt eine ausführliche Diskussion darüber, wann HashSetoder TreeSethier zu verwenden ist: Hashset vs Treeset

ArrayList vs LinkedList

Ausführliche Diskussion: Wann wird LinkedList über ArrayList verwendet?

Tim B.
quelle
Nett! Aber ich muss Ihren LinkedListvs ArrayListEntscheidungen nicht zustimmen . Erstens LinkedListist es vorzuziehen , wenn die Liste eine signifikante Größe hat . LinkedListhat einen Overhead pro Element, daher ist er in Bezug auf den Speicherverbrauch asymptotisch schlechter als ein ArrayList. Wenn sich der größte Teil des Zugriffs am Ende der Liste befindet, ArrayListist ein vorzuziehen, da er einen zeitlich konstanten zufälligen Elementzugriff ermöglicht. Der Zugriff auf das nth-Element von a LinkedListist eine O(n)Operation. ... Tatsächlich sollte die Entscheidung, eine verknüpfte Liste zu verwenden, so gut wie immer "Nein" sein.
Matt Ball
2
@MattBall Ich stimme dir größtenteils zu. Java LinkedListist jedoch eine doppelt verknüpfte Liste, sodass der Zugriff am Anfang und am Ende schnell erfolgt. Sie werden feststellen, dass von den Zweigen vor allem drei Fragen mit Ja beantwortet werden müssen, bevor ich die Verwendung von empfehlen würde. Mit LinkedListanderen Worten, ich stimme Ihnen zu, dass die Antwort in den meisten Fällen Nein lautet. Dinge wie Warteschlangen und Warteschlangen, bei denen Sie ständig Dinge an den Enden des Listenbereichs hinzufügen und entfernen, sind ein guter Anwendungsfall für LinkedList.
Tim B
@MattBall Die Speichernutzung ist eine viel schwierigere Situation, da bei LinkedListmehr Speicherplatz pro Element ... ArrayListniemals Speicher freigegeben wird . Das heißt, wenn Sie eine Liste haben, die manchmal sehr groß wird, aber normalerweise klein ist, führt dies zu einer ArrayListschlechteren Speicherleistung. Der Speicheraufwand für sich Listselbst ist normalerweise (wenn auch nicht immer) gering im Vergleich zu dem der Elemente, die er ebenfalls enthält.
Tim B
Map<K,V>ist nicht der Teil vonjava.util.collection
Mehraj Malik
@MehrajMalik Hmm, die Kennzeichnung ist nicht eindeutig, da stimme ich zu. Ich meinte Sammlung in java.util. dh java.util. * Sammlungsnamen hier einfügen *
Tim B
66

Zusammenfassung der wichtigsten nicht gleichzeitigen, nicht synchronisierten Sammlungen

Collection: Eine Schnittstelle, die eine ungeordnete "Tasche" von Elementen darstellt, die als "Elemente" bezeichnet wird. Das "nächste" Element ist undefiniert (zufällig).

  • Set: Eine Schnittstelle, die a Collectionohne Duplikate darstellt.
    • HashSet: A Setunterstützt von a Hashtable. Schnellste und kleinste Speichernutzung, wenn die Bestellung unwichtig ist.
    • LinkedHashSet: A HashSetmit dem Hinzufügen einer verknüpften Liste, um Elemente in Einfügereihenfolge zuzuordnen . Das "nächste" Element ist das zuletzt eingefügte Element.
    • TreeSet: A Setwo Elemente nach a geordnet sind Comparator(normalerweise natürliche Reihenfolge ). Langsamste und größte Speichernutzung, jedoch für komparatorbasierte Bestellungen erforderlich.
    • EnumSet: Eine extrem schnelle und effiziente SetAnpassung an einen einzelnen Aufzählungstyp.
  • List: Eine Schnittstelle, die a darstellt, Collectionderen Elemente geordnet sind und deren numerischer Index jeweils ihre Position darstellt, wobei Null das erste und (length - 1)das letzte Element ist.
    • ArrayList: Ein Listvon einem Array unterstütztes Array, bei dem das Array eine Länge ("Kapazität" genannt) hat, die mindestens so groß ist wie die Anzahl der Elemente (die "Größe" der Liste). Wenn die Größe die Kapazität überschreitet (wenn das (capacity + 1)-thElement hinzugefügt wird), wird das Array mit einer neuen Kapazität von neu erstellt. (new length * 1.5)Diese Neuerstellung ist schnell, da sie verwendet wird System.arrayCopy(). Zum Löschen und Einfügen / Hinzufügen von Elementen müssen alle benachbarten Elemente (rechts) in diesen Bereich oder aus diesem heraus verschoben werden. Der Zugriff auf ein Element ist schnell, da nur die Berechnung erforderlich ist (element-zero-address + desired-index * element-size), um seinen Standort zu ermitteln. In den meisten Fällen , eine ArrayListüber eine bevorzugt LinkedList.
    • LinkedList: A wird Listvon einer Reihe von Objekten unterstützt, die jeweils mit ihren "vorherigen" und "nächsten" Nachbarn verknüpft sind. A LinkedListist auch ein Queueund Deque. Der Zugriff auf Elemente erfolgt ab dem ersten oder letzten Element und wird durchlaufen, bis der gewünschte Index erreicht ist. Das Einfügen und Löschen, sobald der gewünschte Index durch Traversal erreicht ist, ist eine triviale Angelegenheit, bei der nur die Links zum unmittelbaren Nachbarn neu zugeordnet werden, um auf das neue Element zu verweisen oder das jetzt gelöschte Element zu umgehen.
  • Map: Eine Schnittstelle, die darstellt, Collectionwo jedes Element einen identifizierenden "Schlüssel" hat - jedes Element ist ein Schlüssel-Wert-Paar.
    • HashMap: A Mapwo Schlüssel ungeordnet sind und von a unterstützt werden Hashtable.
    • LinkedhashMap: Die Schlüssel werden nach Einfügereihenfolge sortiert .
    • TreeMap: A Mapwo Schlüssel nach a geordnet sind Comparator(normalerweise natürliche Reihenfolge).
  • Queue: Eine Schnittstelle, die darstellt, Collectionwo Elemente normalerweise an einem Ende hinzugefügt und vom anderen entfernt werden (FIFO: First-In, First-Out).
  • Stack: Eine Schnittstelle, die darstellt, Collectionwo Elemente normalerweise am selben Ende hinzugefügt (verschoben) und entfernt (gepoppt) werden (LIFO: last-in, first-out).
  • Deque: Abkürzung für "Double Ended Queue", normalerweise ausgesprochen "Deck". Eine verknüpfte Liste, die normalerweise nur zu beiden Enden hinzugefügt und von diesen gelesen wird (nicht von der Mitte).

Grundlegende Sammlungsdiagramme:

Diagramm

Vergleichen der Einfügung eines Elements mit einem ArrayListund LinkedList:

Diagramm

aliteralmind
quelle
2
Am besten in kurzer
Sommerzeit,
11

Ein noch einfacheres Bild ist hier. Absichtlich vereinfacht!

  1. Sammlung ist alles, was Daten enthält, die als "Elemente" (vom gleichen Typ) bezeichnet werden. Es wird nichts Spezifischeres angenommen.

  2. Liste ist eine indizierte Sammlung von Daten, bei der jedes Element einen Index hat. So etwas wie das Array, aber flexibler.

    Die Daten in der Liste behalten die Einfügereihenfolge bei.

    Typische Operation: Holen Sie sich das n-te Element.

  3. Set ist eine Tüte mit Elementen , jedes Element nur einmal (die Elemente werden anhand ihrerequals()Methode unterschieden.

    Die Daten im Set werden meistens nur gespeichert, um zu wissen, welche Daten vorhanden sind.

    Typische Operation: Stellen Sie fest, ob ein Element in der Liste vorhanden ist.

  4. Map ist so etwas wie die Liste, aber anstatt über ihren ganzzahligen Index auf die Elemente zuzugreifen, greifen Sie über ihren Schlüssel , der ein beliebiges Objekt ist, auf sie zu. Wie das Array in PHP :)

    Daten in der Karte können anhand ihres Schlüssels durchsucht werden.

    Typische Operation: Holen Sie sich ein Element anhand seiner ID (wobei ID von einem beliebigen Typ ist, nicht nur intwie im Fall von List).

Die Unterschiede

  • Set und Map: In Set suchen Sie Daten selbst , während Sie in Map nach ihrem Schlüssel suchen .

  • Liste und Karte: In Liste greifen Sie über ihren intIndex (Position in Liste) auf das Element zu , während Sie in Karte über ihren Schlüssel auf ein beliebiges Betriebssystem zugreifen (normalerweise: ID).

  • Liste und Menge: In Liste sind die Elemente an ihre Position gebunden und können dupliziert werden, während in Menge die Elemente nur "vorhanden" (pr nicht vorhanden) und eindeutig (im Sinne von equals()oder compareTo()für SortedSet) sind.

Honza Zidek
quelle
1

Es ist ganz einfach: Wenn Sie Werte mit zugeordneten Schlüsseln speichern müssen, wählen Sie die Map-Oberfläche. Andernfalls verwenden Sie List für Werte, die möglicherweise dupliziert werden, und verwenden Sie schließlich die Set-Schnittstelle, wenn Sie keine doppelten Werte in Ihrer Sammlung haben möchten.

Hier ist die vollständige Erklärung http://javatutorial.net/choose-the-right-java-collection , einschließlich Flussdiagramm usw.

filip_j
quelle
1

Karte

Bei Auswahl von a habe Mapich diese Tabelle erstellt, in der die Funktionen jeder der zehn mit Java 11 gebündelten Implementierungen zusammengefasst sind.

Tabelle der Kartenimplementierungen in Java 11 zum Vergleich ihrer Funktionen

Basil Bourque
quelle
0

Gemeinsame Sammlungen, Gemeinsame Sammlungen Geben Sie hier die Bildbeschreibung ein

Aliaksandr Shpak
quelle
-2

Welche Java Collection soll ich verwenden?

Es hängt davon ab, welches Problem Sie lösen möchten oder welche Anforderungen Sie haben.

Beispiele:

  1. Möchten Sie, dass die Elemente beim Speichern sortiert werden? HashSet
  2. Möchten Sie (Schlüssel, Wert) Paare speichern? HashMap
  3. Möchten Sie, dass die Reihenfolge der Elemente beim Einfügen beibehalten wird? ArrayList, LinkedList
  4. Möchten Sie, dass das Schlüsselpaar (Schlüssel, Wert) sortiert wird? - starker Text
  5. Möchten Sie einen Stack implementieren, um Ihr Problem zu lösen? - Stapeln
  6. Möchten Sie FIFO-Zugriff (First in First out) haben? - Warteschlange
  7. Möchten Sie, dass nur EINZIGARTIGE Elemente gespeichert werden? - HashSet
  8. Möchten Sie den Schlüssel beim Speichern als "Null" zulassen (Schlüssel, Wert)? - HashMap
  9. Möchten Sie keine NULL-Werte für das Paar (Schlüssel, Wert)? Hash-tabelle
Aviral Kumar
quelle
Selbst wenn starker Text in Punkt 4 beispielsweise durch ConcurrentSkipListMap (K, V) ersetzt wird , was trägt diese Antwort zum Entscheidungsdiagramm von Tim B und zu den " Kurzlistenbeschreibungen " von aliteralmind bei ?
Graubart
Ihr erster Punkt, HashSet, sortiert keine Daten, auch die Einfügereihenfolge wird nicht beibehalten. Sie sollten es mit TreeSet
Saurabh Mishra