Siehe die JavaDocs und diesen Vortrag von Stuart Marks (oder früheren Versionen davon).
Für die Codebeispiele verwende ich Folgendes:
List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);
Strukturelle Unveränderlichkeit (oder: Unmodifizierbarkeit)
Jeder Versuch, sich strukturell zu verändern, List.of
führt zu einem UnsupportedOperationException
. 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 auf set
.
listOf.set(1, "a"); // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a"); // modified unmodif! unmodif is not truly unmodifiable
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 nicht null
als Element zulassen . Der Versuch, null
als Element oder sogar als Suche zu übergeben, führt zu a NullPointerException
.
Da Arrays.asList
es sich um eine Sammlung aus 1.2 (dem Collections Framework) handelt, können null
s.
listOf.contains(null); // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null); // allowed
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 Anrufe new 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.
asList1 == asList2; // false
listOf1 == listOf2; // true or false
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.
asList.equals(listOf); // true i.f.f. same elements in same order
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):
static final class List2<E> extends AbstractImmutableList<E> {
private final E e0;
private final E e1;
List2(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
}
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 Beispiele size()
können eine konstante zurückzukehren , ohne die Arraylänge Abrufen und contains(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) mit
Collections.unmodifiableList(Arrays.asList(...));
Dadurch 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 im HashSet
Ä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).