Vedi i JavaDocs e questo discorso di Stuart Marks (o versioni precedenti di esso).
Userò quanto segue per gli esempi di codice:
List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);
Immutabilità strutturale (o: immodificabilità)
Qualsiasi tentativo di cambiare strutturalmenteList.of
si tradurrà in un UnsupportedOperationException
. Ciò include operazioni come aggiungere , impostare e rimuovere . È tuttavia possibile modificare il contenuto degli oggetti nell'elenco (se gli oggetti non sono immutabili), quindi l'elenco non è "completamente immutabile".
Questo è lo stesso destino per gli elenchi non modificabili creati con Collections.unmodifiableList
. Solo questo elenco è una visualizzazione dell'elenco originale, quindi può cambiare se si modifica l'elenco originale.
Arrays.asList
non è completamente immutabile, non ha limitazioni set
.
listOf.set(1, "a"); // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a"); // modified unmodif! unmodif is not truly unmodifiable
Allo stesso modo, cambiando l'array di supporto (se lo tieni premuto) cambierà l'elenco.
L'immutabilità strutturale presenta molti effetti collaterali relativi alla codifica difensiva, alla concorrenza e alla sicurezza che esulano dallo scopo di questa risposta.
Nulla ostilità
List.of
e qualsiasi raccolta a partire da Java 1.5 non consente null
come elemento. Il tentativo di passare null
come elemento o anche una ricerca risulterà in un file NullPointerException
.
Poiché Arrays.asList
è una raccolta da 1.2 (il framework delle raccolte), consente null
s.
listOf.contains(null); // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null); // allowed
Modulo serializzato
Poiché List.of
è stato introdotto in Java 9 e gli elenchi creati con questo metodo hanno il loro formato serializzato (binario), non possono essere deserializzati nelle versioni precedenti di JDK (nessuna compatibilità binaria ). Tuttavia, puoi de / serializzare con JSON, ad esempio.
Identità
Arrays.asList
internamente chiama new ArrayList
, che garantisce la disuguaglianza di riferimento.
List.of
dipende dall'implementazione interna. Le istanze restituite possono avere l'uguaglianza dei riferimenti, ma poiché ciò non è garantito non puoi fare affidamento su di essa.
asList1 == asList2; // false
listOf1 == listOf2; // true or false
Vale la pena ricordare che le liste sono uguali (tramite List.equals
) se contengono gli stessi elementi nello stesso ordine, indipendentemente da come sono state create o da quali operazioni supportano.
asList.equals(listOf); // true i.f.f. same elements in same order
Implementazione (avviso: i dettagli possono cambiare rispetto alle versioni)
Se il numero di elementi nell'elenco di List.of
è 2 o inferiore, gli elementi vengono memorizzati in campi di una classe specializzata (interna). Un esempio è l'elenco che memorizza 2 elementi (sorgente parziale):
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);
}
}
Altrimenti vengono archiviati in una matrice in modo simile a Arrays.asList
.
Efficienza nel tempo e nello spazio
Le List.of
implementazioni basate sul campo (dimensione <2) sono leggermente più veloci su alcune operazioni. Ad esempio, size()
può restituire una costante senza recuperare la lunghezza dell'array e contains(E e)
non richiede un overhead di iterazione.
Anche la costruzione di un elenco non modificabile tramite List.of
è più veloce. Confronta il costruttore precedente con 2 assegnazioni di riferimento (e anche quella per quantità arbitrarie di elementi) con
Collections.unmodifiableList(Arrays.asList(...));
che crea 2 liste più altre spese generali. In termini di spazio, risparmi il UnmodifiableList
wrapper più qualche centesimo. In definitiva, i risparmi HashSet
nell'equivalente sono più convincenti.
Tempo di conclusione: usa List.of
quando vuoi un elenco che non cambia e Arrays.asList
quando vuoi un elenco che può cambiare (come mostrato sopra).