
89. Wie unterscheidet sich eine ArrayList von einer LinkedList?
Dies ist neben der Frage nach der internen Struktur einer HashMap eine der beliebtesten Fragen . Ohne sie ist kein Vorstellungsgespräch vollständig, daher sollte Ihnen die Antwort leicht von der Zunge rollen. Neben dem Offensichtlichen (sie haben unterschiedliche Namen) unterscheiden sie sich auch in ihrer inneren Struktur. Zuvor haben wir die interne Struktur von ArrayList und LinkedList besprochen , daher werde ich nicht näher auf die Implementierungsdetails eingehen. Ich möchte Sie nur daran erinnern, dass ArrayList mithilfe eines internen Arrays implementiert wird, dessen Größe gemäß dieser Formel dynamisch zunimmt:<size of the current array> * 3 / 2 + 1
Darüber hinaus verwendet die Implementierung einer LinkedList eine interne doppelt verknüpfte Liste, d. h. jedes Element hat einen Verweis auf das vorherige und das nächste Element, mit Ausnahme der Elemente am Anfang und Ende der Liste. Interviewer stellen diese Frage gerne so: „Was ist besser, ArrayList oder LinkedList ?“ Ich hoffe, dich zu erwischen. Denn wenn Sie sagen, das eine oder das andere sei besser, dann haben Sie die falsche Antwort gegeben. 
-
Wenn kein Index angegeben ist, wird für beide Arten von Listen automatisch ein neues Element am Ende hinzugefügt. In einer LinkedList wird das neue Element zum neuen Ende (nur ein Referenzpaar wird neu geschrieben, sodass die algorithmische Komplexität O(1) ist ).
Die Add-Methode fügt der letzten leeren Zelle im Array ( O(1) ) ein Element hinzu.
-
Das Hinzufügen eines Elements nach Index bedeutet normalerweise, dass es irgendwo in der Mitte der Liste eingefügt wird. In einer LinkedList sucht die Methode zunächst nach der gewünschten Position, indem sie über die Elemente am Ende und am Kopf iteriert ( O(n/2) ) und fügt dann den Wert ein, indem sie die Referenzen der Elemente auf beiden Seiten der Position überschreibt neues Element wird eingefügt ( O(1) ). Die gesamte algorithmische Komplexität dieser Operation beträgt O(n/2) .
In der gleichen Situation (Hinzufügen nach Index) findet eine ArrayList die gewünschte Position ( O(1) ) und verschiebt dann alle rechts befindlichen Elemente (einschließlich des bereits am angegebenen Index gespeicherten Elements) um eins nach rechts (was erfordert möglicherweise die Erstellung eines neuen internen Arrays und das Kopieren von Elementen dorthin) ( O(n/2) ). Die Gesamtkomplexität beträgt O(n/2) .
-
Das Hinzufügen eines Elements am Anfang einer LinkedList ähnelt dem Hinzufügen eines Elements am Ende: Das neue Element wird zum neuen Kopf ( O(1) ). Für eine ArrayList erfordert dieser Vorgang jedoch das Verschieben aller Elemente nach rechts ( O(n) ).
90. Wie unterscheidet sich eine ArrayList von einem HashSet?
Wenn wir ArrayList und LinkedList Operation für Operation vergleichen könnten, um festzustellen, welche besser ist, wäre ein solcher Vergleich zwischen ArrayList und HashSet für uns nicht so einfach , da es sich um völlig unterschiedliche Sammlungen handelt. Man kann ein Dessert mit einem anderen vergleichen, aber ein Dessert und ein herzhaftes Gericht zu vergleichen ist eine Herausforderung – sie unterscheiden sich schmerzlich. Dennoch werde ich versuchen, einige der Unterschiede zwischen ihnen aufzuzeigen:-
ArrayList implementiert die List- Schnittstelle, während HashSet die Set- Schnittstelle implementiert .
-
Mit ArrayList können Sie über den Index auf ein Element zugreifen: Die Get- Operation hat eine algorithmische Komplexität von O(1) , mit HashSet können Sie jedoch nur über Iteration auf ein gewünschtes Element zugreifen, was zu einer algorithmischen Komplexität im Bereich von O(1) bis O(n) führt .
-
ArrayList erlaubt doppelte Elemente. In einem HashSet sind alle Elemente eindeutig: Jeder Versuch, ein Element hinzuzufügen, das bereits in einem HashSet vorhanden ist , schlägt fehl (Duplikate werden durch Hashcode überprüft, daher der Name dieser Sammlung).
-
ArrayList wird mithilfe eines internen Arrays implementiert, HashSet wird jedoch mithilfe einer internen HashMap implementiert .
-
ArrayList behält die Einfügereihenfolge der Elemente bei, HashSet ist jedoch eine ungeordnete Menge und behält die Reihenfolge der Elemente nicht bei.
-
ArrayList erlaubt eine beliebige Anzahl von Nullwerten, aber Sie können einem HashSet nur einen Nullwert hinzufügen (schließlich müssen die Elemente eindeutig sein).
91. Warum gibt es in Java so viele verschiedene Implementierungen dynamischer Arrays?
Das ist eher eine philosophische Frage. Wir könnten uns auch fragen, warum sie so viele neue und vielfältige Technologien entwickeln? Zur Bequemlichkeit. Das Gleiche gilt auch für eine große Anzahl dynamischer Array-Implementierungen. Keine davon kann als die beste oder ideale Umsetzung bezeichnet werden. Jedes hat in bestimmten Situationen seine Vorteile. Unsere Aufgabe ist es, ihre Unterschiede und ihre Stärken/Schwächen zu kennen, um für die jeweilige Situation die am besten geeignete Sammlung nutzen zu können.92. Warum gibt es in Java so viele verschiedene Schlüsselwertspeicherimplementierungen?
Hier ist die Situation dieselbe wie bei den dynamischen Array-Implementierungen. Es gibt definitiv keine, die allgemein besser ist als die anderen: Jeder hat Stärken und Schwächen. Und natürlich müssen wir ihre Stärken optimal nutzen. Beispiel: Das Concurrent-Paket, das viele Multithread-Klassen enthält, verfügt über eigene Concurrent- Sammlungen. Die ConcurrentHashMap- Klasse hat gegenüber der Standard- HashMap einen Vorteil hinsichtlich der Sicherheit beim Arbeiten mit Daten in einer Multithread-Umgebung, allerdings geht dies auf Kosten einer langsameren Leistung. Und Implementierungen, die nicht in jeder Situation die beste Wahl sind, werden nach und nach nicht mehr verwendet. Beispiel: Hashtable , das ursprünglich als Thread-sichere HashMap gedacht war , wurde vergessen und nicht mehr verwendet, da ConcurrentHashMap beim Arbeiten in einer Multithread-Umgebung sogar besser als Hashtable ist.93. Wie sortiere ich eine Sammlung von Elementen?
Als Erstes muss gesagt werden, dass die Klasse, die Sammlungselemente darstellt, die Schnittstelle Comparable implementieren muss, die aus der Methode CompareTo besteht . Oder Sie benötigen eine Klasse, die die Comparator- Schnittstelle einschließlich ihrer Vergleichsmethode implementiert . Beide Methoden geben an, wie Objekte eines bestimmten Typs verglichen werden. Dies ist beim Sortieren von entscheidender Bedeutung, da der Sortieralgorithmus verstehen muss, nach welchem Prinzip Elemente verglichen werden sollen. Dies geschieht hauptsächlich durch die direkte Implementierung von Comparable in der Klasse, die Sie sortieren möchten. Die Verwendung von Comparator ist weniger verbreitet. Angenommen, Sie verwenden eine Klasse aus einer Bibliothek und diese implementiert Comparable nicht , Sie müssen jedoch eine Sammlung ihrer Objekte sortieren. Da Sie den Code dieser Klasse nicht ändern können (außer durch Erweitern), können Sie eine Implementierung von Comparator schreiben , die angibt, wie Objekte der Klasse verglichen werden. Und noch ein Beispiel. Wenn Sie Objekte desselben Typs auf unterschiedliche Weise sortieren müssen, können Sie mehrere Comparator- Implementierungen schreiben, um sie in verschiedenen Situationen zu verwenden. In der Regel implementieren viele Out-of-the-Box-Klassen, z. B. String , bereits das Comparable- Interface. Das bedeutet, dass Sie sich keine Gedanken über den Vergleich dieser Klassen machen müssen. Sie können sie einfach nutzen. Der erste und offensichtlichste Weg ist die Verwendung der TreeSet- oder TreeMap- Klasse. Diese Klassen speichern Elemente in sortierter Reihenfolge basierend auf dem von den Klassenelementen implementierten Komparator. Vergessen Sie nicht, dass TreeMap Schlüssel und keine Werte sortiert. Wenn Sie Comparator anstelle von Comparable verwenden , müssen Sie beim Erstellen ein Comparator- Objekt an den Konstruktor der Sammlung übergeben:TreeSet treeSet = new TreeSet(customComparator);
Aber was ist, wenn Sie eine andere Art von Sammlung haben? Wie sortiert man es? In diesem Fall ist die zweite Möglichkeit der Collections- Dienstprogrammklasse – die Methode sort() – geeignet. Die Methode ist statisch, Sie müssen also lediglich den Namen der Klasse voranstellen und dann die zu sortierende Liste übergeben. Zum Beispiel:
Collections.sort(someList);
Wenn Sie eine Implementierung von Comparator anstelle von Comparable verwenden , müssen Sie diese als zweites Argument übergeben:
Collections.sort(someList, customComparator);
Diese Operation ändert die interne Reihenfolge der Elemente in der übergebenen Liste: Die Liste wird mithilfe des Komparators sortiert. Beachten Sie, dass die übergebene Liste veränderbar sein muss, andernfalls schlägt die Methode fehl und wirft eine UnsupportedOperationException aus . Eine dritte Möglichkeit besteht darin, die sortierte Methode der Stream- Klasse zu verwenden , die die Elemente der Sammlung sortiert. Wenn wir Comparable verwenden :
someList = someList.stream().sorted().collect(Collectors.toList());
Wenn wir Comparator verwenden :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
Die vierte Möglichkeit besteht darin, manuell einen Sortieralgorithmus zu implementieren, z. B. Blasensortierung
oder Zusammenführungssortierung
.
Objektklasse. equal() und hashCode()
94. Geben Sie eine kurze Beschreibung der Object-Klasse in Java.
Im zweiten Teil der Rezension haben wir bereits die Methoden der Object- Klasse besprochen. Hier möchte ich Sie daran erinnern, dass die Object- Klasse ein Vorfahre jeder Klasse in Java ist. Es verfügt über 11 Methoden, die wiederum von allen Klassen geerbt werden.
95. Wofür werden equal() und hashCode() in Java verwendet?
hashCode() ist eine Methode der Object- Klasse, die von allen Klassen geerbt wird. Seine Aufgabe besteht darin, eine Zahl zu generieren, die ein bestimmtes Objekt darstellt. Ein Beispiel für diese Methode in Aktion finden Sie in HashMap , wo sie für Schlüsselobjekte aufgerufen wird, um den lokalen Hashcode abzurufen, der bestimmt, in welchem Bucket (Zelle des internen Arrays) das Schlüssel-Wert-Paar gespeichert wird. Außerdem Diese Methode wird im Allgemeinen in der Methode equal() als eine ihrer Hauptmethoden zur Identifizierung von Objekten verwendet . equal() ist eine Methode der Object- Klasse, deren Aufgabe es ist, Objekte zu vergleichen und festzustellen, ob sie gleich sind. Diese Methode wird überall dort verwendet, wo wir Objekte vergleichen müssen, da der Standard - Vergleichsoperator == nicht für Objekte geeignet ist, da er nur Objektreferenzen vergleicht.96. Erzählen Sie uns etwas über den Vertrag zwischen equal() und hashCode() in Java?
Lassen Sie mich zunächst sagen, dass die Methoden equal() und hashCode() korrekt überschrieben werden müssen, damit sie ordnungsgemäß funktionieren. Ihre neuen Implementierungen müssen diesen Regeln folgen:- Identische Objekte, für die „equals“ den Wert „true“ zurückgibt, müssen die gleichen Hashcodes haben.
- Objekte mit denselben Hash-Codes sind nicht unbedingt gleich.
GO TO FULL VERSION