JavaRush /Java-Blog /Random-DE /Die 10 häufigsten Fragen zu Sammlungen in Java
FedoraLinux
Level 21
Москва

Die 10 häufigsten Fragen zu Sammlungen in Java

Veröffentlicht in der Gruppe Random-DE
Der Artikel ist eine Übersetzung des Artikels Top 10 Fragen zu Java Collections . Nachfolgend finden Sie die häufigsten Fragen zu Sammlungen in Java, die auf Stackowerflow gestellt und diskutiert werden. Bevor Sie sich mit diesen Fragen befassen, wäre es gut, einen Blick auf das Klassenhierarchiediagramm zu werfen. 1. Wann sollte LinkedList anstelle von ArrayList verwendet werden? Eine ArrayList ist eigentlich ein Array; auf seine Elemente kann direkt über den Index zugegriffen werden. Sollte das Array überlaufen, ist ein neues mit mehr Platz notwendig. Das Platzieren und Verschieben aller Elemente dauert O(n) Zeit. Außerdem ist das Hinzufügen und Entfernen von Elementen erforderlich, um vorhandene Elemente im Array zu verschieben. Dies ist vielleicht der größte Nachteil bei der Verwendung von ArrayList. LinkedList ist eine doppelte Liste von Elementlinks. Um auf das Element in der Mitte zuzugreifen, müssen Sie also vom Anfang bis zum Ende des Blattes suchen. Andererseits ist das Hinzufügen und Entfernen eines Elements in einer LinkedList schneller, da diese Vorgänge nur die Liste selbst ändern. Im Folgenden werden die schlimmsten Zeiten verglichen:
Methode Anordnungsliste LinkedList
get(index) O(1) An)
hinzufügen(E) An) O(1)
add(E, Index) An) An)
entfernen(Index) An) An)
Iterator.remove() An) O(1)
Iterator.add(E) An) O(1)
Trotz der Laufzeit muss bei großen Listen die Speichernutzung individuell betrachtet werden. In einer LinkedList muss jeder Knoten mindestens zwei zusätzliche Zeiger haben, um den vorherigen und den nächsten Knoten zu verknüpfen, während in einer ArrayList nur ein Array von Elementen erforderlich ist. Weitere Vergleiche von ArrayList-, LinkedList- und Vector- Listen . 2. Effizientes Äquivalent zum Entfernen von Elementen während der Sammlungsiteration. Die einzig richtige Möglichkeit, eine Sammlung während der Iteration zu ändern (Elemente zu entfernen), ist die Verwendung von Iterator.remove() . Beispiel: Der häufigste Fehler ist: Beim Ausführen des obigen Codes wird eine ConcurrentModificationException angezeigt . Dies geschieht, weil der Iterator so generiert wurde, dass er sich durch die gesamte Liste bewegt, aber gleichzeitig das Blatt durch den Aufruf von Iterator.remove() geändert wird. Wie in der Dokumentation zu dieser Ausnahme beschrieben, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
„Es ist im Allgemeinen nicht zulässig, dass ein Thread eine Sammlung ändert, während ein anderer Thread darüber iteriert.“
Im Allgemeinen ist es nicht akzeptabel, dass ein Thread eine Sammlung ändert, während ein anderer Thread sie durchläuft. 3. Wie konvertiere ich eine Liste in ein int[]-Array? Der einfachste Weg, dies zu tun, ist die Verwendung von ArrayUtils , das sich in der Apache Commons Lang- Bibliothek befindet . int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); Für diesen Ausdruck gibt es im JDK keine Verknüpfung. Denken Sie daran, dass Sie List.toArray() nicht verwenden können, da dieser Ausdruck List in Integer[] konvertiert (was kein primitiver Typ ist). Der richtige Weg wäre die folgende Option: int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } 4. Wie konvertiere ich ein int[]-Array in eine Liste? Der einfachste Weg ist auch die Verwendung von ArrayUtils in der Apache Commons Lang- Bibliothek , wie oben beschrieben. List list = Arrays.asList(ArrayUtils.toObject(array)); Außerdem gibt es im JDK keine Verknüpfung für diesen Ausdruck. 5. Wie kann ich die Sammlung am besten filtern? Sie können Pakete von Drittanbietern wie Guava oder Apache Commons Lang verwenden , um die Funktionalität zu erhöhen. Beide Pakete verfügen über eine filter()-Methode (in der Collections2- Klasse von Guava und CollectionUtils von Apache). Die Methode filter() gibt Elemente zurück, die mit dem angegebenen Prädikat übereinstimmen. Im JDK ist alles komplizierter. Die gute Nachricht ist, dass in Java 8 Prädikate hinzugefügt werden , aber jetzt müssen Sie Iterator verwenden, um die gesamte Sammlung zu durchlaufen. Natürlich können Sie den von Guava und Apache eingeschlagenen Weg nachahmen, indem Sie sich mit der neuen Predicate-Schnittstelle vertraut machen. Jetzt können wir den folgenden Code verwenden, um die Sammlung zu filtern: 6. Wie konvertiert man List einfach in Set? Dafür gibt es zwei Möglichkeiten, je nachdem, wie Sie Gleichheit definieren möchten. Der erste Codeteil fügt die Liste in ein HashSet ein. Das Duplikat wird in diesem Fall hauptsächlich durch hashCode() bestimmt. Normalerweise funktioniert das. Wenn Sie jedoch den Vergleichspfad berücksichtigen müssen, ist es besser, den zweiten Teil des Codes zu verwenden, in dem Sie Ihren eigenen Komparator definieren können. 7. Wie kann ich doppelte Elemente aus einer ArrayList entfernen? Diese Frage hängt in gewisser Weise mit der obigen Frage zusammen. Wenn Ihnen die Reihenfolge der Elemente in der ArrayList egal ist, wäre es ein kluger Schachzug, das Blatt in einem Set zu platzieren, um Duplikate zu entfernen, und es dann wieder in die Liste zurückzugeben. Unten finden Sie ein Beispiel. Wenn Ihnen die Reihenfolge der Elemente wichtig ist, können Sie die Reihenfolge sicherstellen, indem Sie die Liste in einem LinkedHashSet platzieren , das im Standard-JDK enthalten ist. 8. Sortierte Sammlung int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Es gibt mehrere Möglichkeiten, eine sortierte Sammlung in Java zu unterstützen. Alle bieten eine Sammlung in natürlicher Reihenfolge oder nach einem bestimmten Komparator. Bei natürlicher Reihenfolge müssen Sie auch die Comparable- Schnittstelle für das Element implementieren.
  1. Collections.sort() kann eine Liste sortieren. Wie in der Java-Dokumentation angegeben, ist diese Sortierung stabil und garantiert eine Leistung von n log(n).
  2. PriorityQueue sorgt für eine geordnete Warteschlange. Der Unterschied zwischen PriorityQueue und Collections.sort() besteht darin, dass PriorityQueue die Reihenfolge der Warteschlange ständig beibehält, Sie jedoch nur das erste Element der Warteschlange abrufen können. Sie können nicht zufällig auf ein Element wie PriorityQueue.get(4) zugreifen.
  3. Wenn in der Sammlung keine Duplikate vorhanden sind, können Sie TreeSet auswählen . Ebenso wie PriorityQueue verwaltet TreeSet jederzeit eine geordnete Menge. Sie können das kleinste oder größte Element aus einem TreeSet abrufen, haben aber trotzdem keinen wahlfreien Zugriff auf die Elemente.
Einfach ausgedrückt stellt Collections.sort() eine einmalig geordnete Liste bereit. PriorityQueue und TreeSet verwalten jederzeit eine geordnete Sammlung, allerdings auf Kosten des fehlenden indizierten Zugriffs auf Elemente. 9. Collections.emptyList() oder neue Instanz Die gleiche Frage gilt für emptyMap() und emptySet(). Beide Methoden geben eine leere Liste zurück, Collections.emptyList() ist jedoch eine unveränderliche Liste. Das bedeutet, dass Sie einer „leeren“ Liste keine neuen Elemente hinzufügen können . Im Hintergrund erstellt jeder Aufruf der Collections.emptyList()-Methode nicht tatsächlich eine neue Instanz der leeren Liste. Stattdessen wird die bereits vorhandene leere Instanz wiederverwendet. Wenn Sie Singleton als Entwurfsmuster kennen , sollten Sie verstehen, was gemeint ist. Dies sollte bei häufigen Anrufen zu einer besseren Leistung führen . 10 Eine Sammlung kopieren, Collections.copy() Es gibt zwei Möglichkeiten, eine Quellliste in eine Zielliste zu kopieren. Eine Möglichkeit besteht darin, den ArrayList-Konstruktor zu verwenden. Eine andere Möglichkeit ist die Verwendung der Collections.copy()- Methode . Beachten Sie die erste Zeile: Wir weisen eine Liste zu, die mindestens so lang ist wie die ursprüngliche Liste, da in der Java-Dokumentation zu Sammlungen Folgendes steht: ArrayList dstList = new ArrayList (srcList);
Die Zielliste muss mindestens so lang sein wie die Quellliste.
Das bedeutet, dass die endgültige Liste nicht kürzer sein darf als die ursprüngliche. Bei beiden Methoden handelt es sich um flaches Kopieren. Was ist also der Unterschied zwischen diesen beiden Methoden? Erstens weist Collections.copy() die Kapazität der dstList-Sammlung nicht neu zu, selbst wenn die dstList nicht über genügend Platz verfügt, um alle Elemente aus der srcList aufzunehmen. Stattdessen wird eine IndexOutOfBoundsException ausgelöst . Man könnte sich fragen, ob das irgendeinen Vorteil hat. Der Grund dafür ist, dass dadurch sichergestellt wird, dass die Methode zeitlich linear abläuft. Dies eignet sich auch, wenn Sie Arrays wiederverwenden möchten, anstatt Speicher im ArrayList-Konstruktor neu zuzuweisen. Anstelle eines Fazits Wenn Sie nach der Lektüre des Artikels noch Fragen haben, können Sie diese gerne in den Kommentaren stellen. Wenn Sie außerdem eine Ungenauigkeit in der Übersetzung oder einen anderen Fehler feststellen, schreiben Sie an die PM, sie wird korrigiert und es wird Ihnen gedankt. Original. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION