Ich versuche zu verstehen, warum Javas ArrayDeque besser ist als Javas LinkedList, da beide die Deque-Schnittstelle implementieren.
Ich sehe kaum jemanden, der ArrayDeque in seinem Code verwendet. Wenn jemand mehr Licht in die Implementierung von ArrayDeque bringt, wäre dies hilfreich.
Wenn ich es verstehe, werde ich sicherer damit umgehen. Ich konnte die JDK-Implementierung hinsichtlich der Art und Weise, wie Head- und Tail-Referenzen verwaltet werden, nicht klar verstehen.
java
deque
linked-list
arraydeque
Grausam
quelle
quelle
src.zip
. Es ist das Archiv mit dem Quellcode der Java-Klassen. Ich empfehle dringend, diese Klassenstruktur und Interna zu studieren, um besser zu verstehen, wie Java-Klassen funktionieren.Antworten:
Verknüpfte Strukturen sind möglicherweise die schlechteste Struktur, die mit einem Cache-Fehler für jedes Element iteriert werden kann. Darüber hinaus verbrauchen sie viel mehr Speicher.
Wenn Sie beide Enden hinzufügen / entfernen müssen, ist ArrayDeque deutlich besser als eine verknüpfte Liste. Der Direktzugriff auf jedes Element ist für eine zyklische Warteschlange ebenfalls O (1).
Die einzig bessere Operation einer verknüpften Liste besteht darin, das aktuelle Element während der Iteration zu entfernen.
quelle
LinkedList
Implementiert auch,List
währendArrayDeque
dies nicht der Fall ist. Dies bedeutet,LinkedList
dass Methoden wieindexOf
oderremove(int)
währendArrayDeque
nicht haben. Es kann manchmal wichtig sein.Ich glaube, dass der größte Leistungsengpass darin
LinkedList
besteht, dass die Implementierung hinter den Kulissen immer dann, wenn Sie an ein Ende der Deque drängen, einen neuen Knoten für verknüpfte Listen zuweist, der im Wesentlichen JVM / OS umfasst, und das ist teuer. Wenn Sie von einem beliebigen Ende aus auftauchen, können die internen Knoten vonLinkedList
für die Speicherbereinigung verwendet werden, und das ist mehr Arbeit hinter den Kulissen. Da die verknüpften Listenknoten hier und da zugewiesen werden, bietet die Verwendung des CPU-Cache keinen großen Vorteil.Wenn es von Interesse sein könnte, habe ich einen Beweis dafür, dass das Hinzufügen (Anhängen) eines Elements zu
ArrayList
oderArrayDeque
die Ausführung in einer amortisierten konstanten Zeit erfolgt; beziehen sich darauf .quelle
ArrayDeque
ist neu in Java 6, weshalb viele Codes (insbesondere Projekte, die versuchen, mit früheren Java-Versionen kompatibel zu sein) es nicht verwenden.In einigen Fällen ist dies "besser", da Sie nicht jedem einzufügenden Element einen Knoten zuweisen. Stattdessen werden alle Elemente in einem riesigen Array gespeichert, dessen Größe geändert wird, wenn es voll wird.
quelle
Alle Leute, die a kritisieren
LinkedList
, denken an jeden anderen Typ, derList
in Java verwendet hat, wahrscheinlichArrayList
undLinkedList
meistens, weil sie vor Java 6 waren und weil dies diejenigen sind, die in den meisten Büchern als Anfang gelehrt werden.Das heißt aber nicht, dass ich blindlings auf
LinkedList
derArrayDeque
Seite von oder stehen würde . Wenn Sie es wissen möchten, werfen Sie einen Blick auf den folgenden Benchmark von Brian .Der Testaufbau berücksichtigt:
Testergebnis:
Graph:
Wegbringen:
ArrayList
oderArrayDeque
mit einer guten Schätzung der maximalen Kapazität verwenden, die die Liste aufgrund strenger Speicherbeschränkungen möglicherweise benötigt.LinkedList
so sorgfältigen Profil geschrieben wurde, wenn Sie sich für die Verwendung von a entschieden haben,ArrayDeque
insbesondere, weil es dieList
Schnittstelle NICHT implementiert (ich denke, das ist der Grund, der groß genug ist). Es kann sein, dass Ihre Codebasis höchstwahrscheinlich ausführlich mit der List-Oberfläche kommuniziert und Sie sich entscheiden, mit einem zu springenArrayDeque
. Die Verwendung für interne Implementierungen könnte eine gute Idee sein ...quelle
ArrayDeque und LinkedList implementieren die Deque- Schnittstelle, die Implementierung ist jedoch unterschiedlich.
Hauptunterschiede:
Die ArrayDeque- Klasse ist die anpassbare Array-Implementierung der Deque- Schnittstelle und die LinkedList- Klasse ist die Listenimplementierung
NULL-Elemente können zu LinkedList hinzugefügt werden, jedoch nicht in ArrayDeque
ArrayDeque ist effizienter als die LinkedList für das Hinzufügen und Entfernen an beiden Enden, und die LinkedList-Implementierung ist effizient zum Entfernen des aktuellen Elements während der Iteration
Die LinkedList- Implementierung belegt mehr Speicher als die ArrayDeque
Wenn Sie also keine NULL-Elemente unterstützen müssen und weniger Speicher und Effizienz beim Hinzufügen / Entfernen von Elementen an beiden Enden suchen, ist ArrayDeque das Beste
Weitere Informationen finden Sie in der Dokumentation .
quelle
header.previous.element
) zu erhalten. Die Behauptung "Speichereffizienz" kann auch angefochten werden, da die Größe des Hintergrundarrays immer auf die nächste Potenz von 2Iterator
mit a auf das letzte Element zugreifen, lautet die Operation für beide Klassen O (N). Wenn Sie die gemeinsameDeque
Schnittstelle verwenden, ist der Zugriff auf das letzte Element für beide Klassen O (1). Unabhängig davon, welchen Standpunkt Sie einnehmen, schreiben Sie O (1) zuArrayDeque
LinkedList
, ist es falsch und O (N) gleichzeitig zuzuweisen.Obwohl
ArrayDeque<E>
undLinkedList<E>
beideDeque<E>
Interface implementiert haben , verwendet ArrayDeque im Grunde genommen das Object-Array,E[]
um die Elemente in seinem Objekt zu belassen. Daher verwendet es im Allgemeinen den Index zum Lokalisieren der Head- und Tail-Elemente.Mit einem Wort, es funktioniert genau wie Deque (mit allen Deque-Methoden), verwendet jedoch die Datenstruktur des Arrays. Welche besser ist, hängt davon ab, wie und wo Sie sie verwenden.
quelle
Das ist nicht immer der Fall.
Zum Beispiel hat im folgenden Fall
linkedlist
eine bessere Leistung alsArrayDeque
gemäß Leetcode 103.quelle
Die zeitliche Komplexität für ArrayDeque für den Zugriff auf ein Element beträgt O (1) und für LinkList O (N) für den Zugriff auf das letzte Element. ArrayDeque ist nicht threadsicher, daher ist eine manuelle Synchronisierung erforderlich, damit Sie über mehrere Threads darauf zugreifen können und diese schneller sind.
quelle
LinkedList
Java beziehenCollection
, ist es doppelt verknüpft und hat schnellen Zugriff auf Kopf und Schwanz, sodass der Zugriff auf das letzte Element auch O (1) erfordert.