Big-O-Zusammenfassung für Java Collections Framework-Implementierungen? [geschlossen]

164

Möglicherweise unterrichte ich bald einen "Java-Crash-Kurs". Während es wahrscheinlich sicher ist anzunehmen, dass die Zuschauer die Big-O-Notation kennen, ist es wahrscheinlich nicht sicher anzunehmen, dass sie die Reihenfolge der verschiedenen Operationen auf verschiedenen Sammlungsimplementierungen kennen.

Ich könnte mir Zeit nehmen, um selbst eine Zusammenfassungsmatrix zu erstellen, aber wenn sie bereits irgendwo öffentlich verfügbar ist, würde ich sie gerne wiederverwenden (natürlich mit angemessener Gutschrift).

Hat jemand irgendwelche Hinweise?

Jared
quelle
Hier ist ein Link, den ich als nützlich empfand, wenn ich einige sehr häufige Java-Objekte diskutierte und wie viel ihre Operationen mit der Big-O-Notation kosten. objectissues.blogspot.com/2006/11/…
Nick
Die hervorragenden Java-Generika und -Sammlungen von Maurice Naftalin und Philip Wadler sind zwar nicht gemeinfrei, enthalten jedoch in ihren Kapiteln Übersichten zu Laufzeitinformationen zu den verschiedenen Sammlungsklassen.
Fabian Steeg
1
Wäre dieser Leistungsbenchmark von Nutzen?
Bedrohung

Antworten:

149

Diese Website ist ziemlich gut, aber nicht spezifisch für Java: http://bigocheatsheet.com/ Hier ist ein Bild für den Fall, dass dieser Link nicht funktioniert

Ben J.
quelle
27
Und deshalb verwenden wir keine URLs als Antworten. Dieses Dokument / dieser Server ist, soweit ich das beurteilen kann, nicht mehr verfügbar!
Jason Mock
1
@ Ben J Links funktionieren nicht mehr
Vikas V
Die Webarchiv-Links sind jetzt ebenfalls defekt.
MikeFHay
Scheint, als würden neue Arbeits-URLs hinzugefügt. Vielen Dank für die Mühe, es ist sehr hilfreich.
Tejas C
1
@AndreaZilio LinkedList.remove (Object) ist eine konstante Zeit, vorausgesetzt, Sie kennen den Nachbarn bereits. Wenn Sie den Nachbarn nicht kennen, ist es lineare Zeit, ihn zuerst zu finden.
Paul Evans
217

Das Buch Java Generics and Collections enthält diese Informationen (Seiten: 188, 211, 222, 240).

Listenimplementierungen:

                      get  add  contains next remove(0) iterator.remove
ArrayList             O(1) O(1) O(n)     O(1) O(n)      O(n)
LinkedList            O(n) O(1) O(n)     O(1) O(1)      O(1)
CopyOnWrite-ArrayList O(1) O(n) O(n)     O(1) O(n)      O(n)

Implementierungen festlegen:

                      add      contains next     notes
HashSet               O(1)     O(1)     O(h/n)   h is the table capacity
LinkedHashSet         O(1)     O(1)     O(1) 
CopyOnWriteArraySet   O(n)     O(n)     O(1) 
EnumSet               O(1)     O(1)     O(1) 
TreeSet               O(log n) O(log n) O(log n)
ConcurrentSkipListSet O(log n) O(log n) O(1)

Kartenimplementierungen:

                      get      containsKey next     Notes
HashMap               O(1)     O(1)        O(h/n)   h is the table capacity
LinkedHashMap         O(1)     O(1)        O(1) 
IdentityHashMap       O(1)     O(1)        O(h/n)   h is the table capacity 
EnumMap               O(1)     O(1)        O(1) 
TreeMap               O(log n) O(log n)    O(log n) 
ConcurrentHashMap     O(1)     O(1)        O(h/n)   h is the table capacity 
ConcurrentSkipListMap O(log n) O(log n)    O(1)

Warteschlangenimplementierungen:

                      offer    peek poll     size
PriorityQueue         O(log n) O(1) O(log n) O(1)
ConcurrentLinkedQueue O(1)     O(1) O(1)     O(n)
ArrayBlockingQueue    O(1)     O(1) O(1)     O(1)
LinkedBlockingQueue   O(1)     O(1) O(1)     O(1)
PriorityBlockingQueue O(log n) O(1) O(log n) O(1)
DelayQueue            O(log n) O(1) O(log n) O(1)
LinkedList            O(1)     O(1) O(1)     O(1)
ArrayDeque            O(1)     O(1) O(1)     O(1)
LinkedBlockingDeque   O(1)     O(1) O(1)     O(1)

Das Ende des Javadoc für das Paket java.util enthält einige gute Links:

Toolkit
quelle
3
Sie müssen angeben, für welches Szenario diese Zahlen gelten. Wenn Sie beispielsweise ein Element in der Mitte oder am Ende des Arrays löschen, kann das Löschen aus Arraylist O (n) annehmen.
Popeye
@ Popeye ist O normalerweise nicht der schlimmste Fall?
Yassin Hajaj
Wie von @Popeye erwähnt, sollte es eine klare Beschreibung darüber geben, um welchen Fall es sich bei der Antwort handelt. Der Fall kann für die zeitliche Komplexität entweder durchschnittlich oder am schlechtesten sein. Es sieht so aus, als würde sich die Antwort auf einen "durchschnittlichen" Fall für alle DS beziehen.
Yashwin Munsadwala
12

Die Javadocs von Sun für jede Sammlungsklasse sagen Ihnen im Allgemeinen genau, was Sie wollen. HashMap zum Beispiel:

Diese Implementierung bietet eine zeitkonstante Leistung für die Grundoperationen (get und put), vorausgesetzt, die Hash-Funktion verteilt die Elemente ordnungsgemäß auf die Buckets. Die Iteration über Sammlungsansichten erfordert Zeit, die proportional zur "Kapazität" der HashMap-Instanz (Anzahl der Buckets) plus ihrer Größe (Anzahl der Schlüsselwertzuordnungen) ist.

Baumkarte :

Diese Implementierung bietet garantierte Protokoll (n) -Zeitkosten für die ContainsKey-, Get-, Put- und Remove-Vorgänge.

TreeSet :

Diese Implementierung bietet garantierte log (n) Zeitkosten für die grundlegenden Vorgänge (Hinzufügen, Entfernen und Enthalten).

(Hervorhebung von mir)

matt b
quelle
Ich bin mit dem HashMap-Teil nicht einverstanden. Ich kenne die Position von Sun, aber ... get muss zum Beispiel obj.equals (key) aufrufen, was in der Größe der enthaltenen Objekte linear sein kann. Beachten Sie, dass Sie normalerweise die Felder für diesen Vergleich lesen müssen. Die Ausnahmen wären ganze Zahlen oder Zeichenfolgen (interniert) ???
Überflogen
Wenn sie falsch waren, sollte es für Sie nicht allzu schwierig sein, einen Testfall zu erstellen, der die Leistung bei konstanter Zeit widerlegt. Zweitens, wenn Sie sich den Quellcode für HashMap ansehen, ruft er nicht equals () für jeden Schlüssel in der Map auf - nur wenn die Hashcodes gleich sind.
Matt B
5
Wenn Sie das obige Zitat lesen, heißt es, dass es eine konstante Zeit ist, "vorausgesetzt, die Hash-Funktion verteilt die Elemente richtig auf die Buckets". Nach der CS-Theorie haben Hash-Tabellen konstante Zeitoperationen, wenn die Hash-Funktion "gut" ist (was im Durchschnitt passiert), können aber im schlimmsten Fall lineare Zeit in Anspruch nehmen.
Newacct
4
@Overflown - technisch gesehen spielt es aus Komplexitätssicht keine Rolle, wie lange obj.equals () dauert, da dies nur ein Teil der "Konstante" in Bezug auf die Anzahl der Elemente in der Sammlung ist.
Mikera
6

Der Typ oben gab einen Vergleich zwischen HashMap / HashSet und TreeMap / TreeSet.

Ich werde über ArrayList vs. LinkedList sprechen:

Anordnungsliste:

  • O (1) get()
  • amortisiert O (1) add()
  • Wenn Sie ein Element in der Mitte mit ListIterator.add()oder einfügen oder löschen Iterator.remove(), ist es O (n), um alle folgenden Elemente zu verschieben

LinkedList:

  • Auf) get()
  • O (1) add()
  • Wenn Sie ein Element in der Mitte mit ListIterator.add()oder einfügen oder löschen Iterator.remove(), ist es O (1).
newacct
quelle
1
if you insert or delete an element in the middle using ListIterator.add() or Iterator.remove(), it will be O(1) Warum? Zuerst müssen wir das Element in der Mitte finden. Warum also nicht O (n)?
MyTitle
@ MyTitle: Lies es noch einmal. "using ListIterator.add()or Iterator.remove()" Wir haben einen Iterator.
Newacct