Voir le JavaDocs et ceci parler de Stuart Marks (ou des versions précédentes).
Je vais utiliser les éléments suivants pour les exemples de code :
List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);
Immuabilité structurelle (ou : non-modifiabilité)
Toute tentative de structurellement changement List.of
se traduira par un UnsupportedOperationException
. Cela comprend des opérations telles que ajouter , set et supprimer . Vous pouvez toutefois modifier le contenu des objets de la liste (si les objets ne sont pas immuables), la liste n'est donc pas "totalement immuable".
C'est le même sort pour les listes non modifiables créées avec Collections.unmodifiableList
. Seule cette liste est une voir de la liste d'origine, elle peut donc changer si vous modifiez la liste d'origine.
Arrays.asList
n'est pas complètement immuable, il n'a pas de restriction sur les set
.
listOf.set(1, "a"); // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a"); // modified unmodif! unmodif is not truly unmodifiable
De même, le changement du tableau de support (si vous le détenez) modifiera la liste.
L'immuabilité structurelle s'accompagne de nombreux effets secondaires liés au codage défensif, à la concurrence et à la sécurité, qui dépassent le cadre de cette réponse.
Hostilité nulle
List.of
et toute collection depuis Java 1.5 n'autorisent pas null
comme un élément. Tenter de passer null
en tant qu'élément ou même en tant que recherche donnera lieu à une NullPointerException
.
Depuis Arrays.asList
est une collection de la 1.2 (le cadre des collections), elle permet de null
s.
listOf.contains(null); // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null); // allowed
Forme sérialisée
Depuis List.of
a été introduit dans Java 9 et les listes créées par cette méthode ont leur propre forme sérialisée (binaire), elles ne peuvent pas être désérialisées sur les versions antérieures du JDK (pas de compatibilité binaire ). Toutefois, vous pouvez effectuer des opérations de sérialisation avec JSON, par exemple.
Identité
Arrays.asList
appels internes new ArrayList
ce qui garantit l'inégalité de référence.
List.of
dépend de la mise en œuvre interne. Les instances retournées peuvent avoir une égalité de référence, mais comme cela n'est pas garanti, vous ne pouvez pas vous y fier.
asList1 == asList2; // false
listOf1 == listOf2; // true or false
Il convient de mentionner que les listes sont égales (via List.equals
) s'ils contiennent les mêmes éléments dans le même ordre, indépendamment de la façon dont ils ont été créés ou des opérations qu'ils supportent.
asList.equals(listOf); // true i.f.f. same elements in same order
Mise en œuvre (attention : les détails peuvent changer au fil des versions)
Si le nombre d'éléments dans la liste de List.of
est égal ou inférieur à 2, les éléments sont stockés dans des champs d'une classe spécialisée (interne). Un exemple est la liste qui stocke 2 éléments (source partielle) :
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);
}
}
Sinon, ils sont stockés dans un tableau de façon similaire à Arrays.asList
.
Efficacité du temps et de l'espace
Le site List.of
Les implémentations basées sur les champs (taille<2) sont légèrement plus rapides pour certaines opérations. À titre d'exemple, size()
peut retourner une constante sans récupérer la longueur du tableau, et contains(E e)
ne nécessite pas de surcharge d'itération.
Construction d'une liste non modifiable via List.of
est également plus rapide. Comparez le constructeur ci-dessus avec 2 affectations de référence (et même celui pour un nombre arbitraire d'éléments) à
Collections.unmodifiableList(Arrays.asList(...));
ce qui crée 2 listes plus d'autres frais généraux. En termes d'espace, vous économisez le UnmodifiableList
l'emballage plus quelques centimes. Au final, les économies réalisées dans le HashSet
équivalent sont plus convaincants.
Temps de conclusion : utilisation List.of
quand vous voulez une liste qui ne change pas et Arrays.asList
lorsque vous voulez une liste qui peut changer (comme indiqué ci-dessus).