Java 9 führte neue Factory-Methoden für Listen ein List.of
:
List<String> strings = List.of("first", "second");
Was ist der Unterschied zwischen der vorherigen und der neuen Option? Das heißt, was ist der Unterschied zwischen diesem:
Arrays.asList(1, 2, 3);
und das:
List.of(1, 2, 3);
Antworten:
Arrays.asList
liefert eine veränderbare Liste , während die Liste zurück durchList.of
ist unveränderlich :Arrays.asList
erlaubt null Elemente, währendList.of
nicht:contains
verhält sich anders mit Nullen:Arrays.asList
Gibt eine Ansicht des übergebenen Arrays zurück, sodass die Änderungen am Array auch in der Liste angezeigt werden. DennList.of
das ist nicht wahr:quelle
List.contains(Object o)
Javadoc des : "Löst eine [...] NullPointerException aus - wenn das angegebene Element null ist und diese Liste keine Nullelemente zulässt (optional)". Oder aus der langen Einführung der Benutzeroberfläche, die nur wenige lesen: "Einige Sammlungsimplementierungen haben Einschränkungen hinsichtlich der Elemente, die sie enthalten können"List.of
nicht etwas zurückgebenImmutableList
Typ, dessen eigentlicher Name ist nur eine nicht-öffentliche Implementierung Detail. Wenn es öffentlich war und jemand esList
erneut besetzte, wo war der Unterschied? Wo ist der Unterschied zuArrays.asList
, der eine nicht öffentlicheList
Implementierung zurückgibt, die beim Versuchadd
oder eine Ausnahme auslöstremove
, oder zu der Liste, vonCollections.unmodifiableList
der zurückgegeben wird , die überhaupt keine Änderung zulässt? Es geht um Verträge, die in derList
Benutzeroberfläche angegeben sind. Die Collections-Schnittstellen mit optionalen Methoden waren seit Java 1.2…Die Unterschiede zwischen
Arrays.asList
undList.of
Siehe die JavaDocs und diesen Vortrag von Stuart Marks (oder früheren Versionen davon).
Für die Codebeispiele verwende ich Folgendes:
Strukturelle Unveränderlichkeit (oder: Unmodifizierbarkeit)
Jeder Versuch, sich strukturell zu verändern,
List.of
führt zu einemUnsupportedOperationException
. Dazu gehören Vorgänge wie Hinzufügen , Festlegen und Entfernen . Sie können jedoch den Inhalt der Objekte in der Liste ändern (wenn die Objekte nicht unveränderlich sind), sodass die Liste nicht "vollständig unveränderlich" ist.Dies ist das gleiche Schicksal für nicht veränderbare Listen, die mit erstellt wurden
Collections.unmodifiableList
. Nur diese Liste ist eine Ansicht der ursprünglichen Liste, sodass sie sich ändern kann, wenn Sie die ursprüngliche Liste ändern.Arrays.asList
ist nicht vollständig unveränderlich, es gibt keine Einschränkung aufset
.In ähnlicher Weise ändert das Ändern des Hintergrundarrays (wenn Sie es gedrückt halten) die Liste.
Strukturelle Unveränderlichkeit bringt viele Nebenwirkungen mit sich, die mit defensiver Codierung, Parallelität und Sicherheit zusammenhängen und über den Rahmen dieser Antwort hinausgehen.
Null Feindseligkeit
List.of
und jede Sammlung seit Java 1.5 nichtnull
als Element zulassen . Der Versuch,null
als Element oder sogar als Suche zu übergeben, führt zu aNullPointerException
.Da
Arrays.asList
es sich um eine Sammlung aus 1.2 (dem Collections Framework) handelt, könnennull
s.Serialisierte Form
Da
List.of
es in Java 9 eingeführt wurde und die mit dieser Methode erstellten Listen eine eigene (binäre) serialisierte Form haben, können sie in früheren JDK-Versionen nicht deserialisiert werden (keine Binärkompatibilität ). Sie können jedoch beispielsweise mit JSON de / serialisieren.Identität
Arrays.asList
Interne Anrufenew ArrayList
, die Referenzungleichheit garantieren.List.of
hängt von der internen Implementierung ab. Die zurückgegebenen Instanzen können Referenzgleichheit haben, aber da dies nicht garantiert ist, können Sie sich nicht darauf verlassen.Erwähnenswert ist, dass Listen gleich sind (via
List.equals
), wenn sie dieselben Elemente in derselben Reihenfolge enthalten, unabhängig davon, wie sie erstellt wurden oder welche Operationen sie unterstützen.Implementierung (Warnung: Details können sich über Versionen ändern)
Wenn die Anzahl der Elemente in der Liste von
List.of
2 oder weniger beträgt, werden die Elemente in Feldern einer speziellen (internen) Klasse gespeichert. Ein Beispiel ist die Liste, in der 2 Elemente gespeichert sind (Teilquelle):Andernfalls werden sie auf ähnliche Weise wie in einem Array gespeichert
Arrays.asList
.Zeit- und Raumeffizienz
Die
List.of
feldbasierten Implementierungen (Größe <2) arbeiten bei einigen Operationen etwas schneller. Als Beispielesize()
können eine konstante zurückzukehren , ohne die Arraylänge Abrufen undcontains(E e)
nicht Iteration Overhead erfordert.Das Erstellen einer nicht veränderbaren Liste über
List.of
ist ebenfalls schneller. Vergleichen Sie den obigen Konstruktor mit 2 Referenzzuweisungen (und sogar der für eine beliebige Anzahl von Elementen) mitDadurch werden 2 Listen plus anderer Overhead erstellt. In Bezug auf den Platz sparen Sie den
UnmodifiableList
Wrapper plus ein paar Cent. Letztendlich sind die Einsparungen imHashSet
Äquivalent überzeugender.Abschlusszeit: Verwenden
List.of
Sie diese Option, wenn Sie eine Liste wünschen, die sich nicht ändert, undArrays.asList
wenn Sie eine Liste möchten, die sich ändern kann (wie oben gezeigt).quelle
Arrays.asList
ist nicht vollständig veränderlich.asList.add(1);
wirft eineUnsupportedOperationException
.List.of
keine Zeit nutzen, die Leute anrufen möchten,contains
und mich nicht von einer NullPointerException überraschen lassen.Fassen wir die Unterschiede zwischen List.of und Arrays.asList zusammen
List.of
kann am besten verwendet werden, wenn der Datensatz kleiner und unverändert ist, währendArrays.asList
am besten bei großen und dynamischen Datensätzen verwendet werden kann.List.of
Nehmen Sie sehr wenig Overhead-Speicherplatz in Anspruch, da die Implementierung vor Ort erfolgt und weniger Heap-Speicherplatz verbraucht wird, sowohl in Bezug auf den festen Overhead als auch auf Elementbasis. währendArrays.asList
nehmen mehr Kopfraum , weil während der Initialisierung es mehr Objekte im Heap erzeugt.Die von zurückgegebene Sammlung
List.of
ist unveränderlich und daher threadsicher, während die von zurückgegebene SammlungArrays.asList
veränderlich und nicht threadsicher ist. (Unveränderliche Sammlungsinstanzen verbrauchen im Allgemeinen viel weniger Speicher als ihre veränderlichen Gegenstücke.)List.of
erlaubt keine Nullelemente , während NullelementeArrays.asList
erlaubt sind.quelle
Arrays.asList
Versus gehtList.of
, da Ersteres buchstäblich nur ein Wrapper um ein Array ist. Zumindest die Implementierung von OpenJDK scheint einen extrem geringen Overhead zu haben. TatsächlichList.of
müssten Kopien aller übergebenen Arrays erstellt werden. Wenn das Array selbst nicht bald einer GC unterzogen wird, scheintList.of
es einen erheblich größeren Speicherbedarf zu haben.List.of(x)
undList.of(x, y)
sind effizienter, weil sie überhaupt keine Arrays zuweisenList.of
Methoden nicht jedes Mal neue Listen zurückgeben müssen. Diese Listen haben eine nicht spezifizierte Identität, sodass auf JVM-Ebene möglicherweise zwischengespeichert, dedupliziert oder skaliert wird. Wenn nicht in dieser Version, dann vielleicht in der nächsten. Es ist vertraglich erlaubt. Im Gegensatz dazuArray.asList
hängt dies von der Identität des Arrays ab, das Sie übergeben, da die resultierende Liste eine veränderbare Ansicht des Arrays ist, die alle Änderungen bidirektional widerspiegelt.Abgesehen von den oben genannten Antworten gibt es bestimmte Operationen an den beide
List::of
undArrays::asList
unterscheiden:Mehr über Informationen zu Collections :: singletonList Vs. Liste von
quelle