Java 9 a introduit une nouvelle méthode d'usine pour les listes, List.of
:
_List<String> strings = List.of("first", "second");
_
Quelle est la différence entre la précédente et la nouvelle option? C'est-à-dire quelle est la différence entre ceci:
_Arrays.asList(1, 2, 3);
_
et ça:
_List.of(1, 2, 3);
_
Arrays.asList
renvoie une liste modifiable alors que la liste renvoyée par List.of
est immuable :
List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK
List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails with UnsupportedOperationException
Arrays.asList
autorise les éléments nuls alors que List.of
ne:
List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with NullPointerException
contains
se comporte différemment avec les NULL:
List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Returns false
List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Fails with NullPointerException
Arrays.asList
renvoie une vue du tableau transmis, ainsi les modifications apportées au tableau seront également reflétées dans la liste. Pour List.of
, ce n'est pas vrai:
Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]
Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]
Arrays.asList
et List.of
Voir le JavaDocs et ceci discussion 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);
_
Toute tentative de structurellement modifier _List.of
_ entraînera un UnsupportedOperationException
. Cela inclut des opérations telles que add , set et supprimer . Vous pouvez toutefois modifier le contenu des objets de la liste (si les objets ne sont pas immuables), de sorte que la liste ne soit pas "complètement immuable".
Il en va de même pour les listes non modifiables créées avec Collections.unmodifiableList
. Seule cette liste est une vue de la liste d'origine. Elle peut donc être modifiée si vous modifiez la liste d'origine.
_Arrays.asList
_ n'est pas complètement immuable, il n'y a pas de restriction sur 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, changer le tableau de sauvegarde (si vous le maintenez) changera la liste.
L’immuabilité structurelle entraîne de nombreux effets secondaires liés au codage défensif, à la simultanéité et à la sécurité qui dépassent le cadre de cette réponse.
_List.of
_ et toute collection depuis Java 1.5 n'autorisent pas null
en tant qu'élément. Si vous tentez de passer null
en tant qu'élément ou même une recherche, vous obtiendrez un NullPointerException
.
Puisque _Arrays.asList
_ est une collection de 1.2 (le framework de collections), il autorise null
s.
_listOf.contains(null); // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null); // allowed
_
Puisque _List.of
_ a été introduit dans Java 9 et que les listes créées par cette méthode ont leur propre formulaire sérialisé (binaire), elles ne peuvent pas être désérialisées sur les versions antérieures du JDK (no compatibilité binaire ). Cependant, vous pouvez dés/sérialiser avec JSON, par exemple.
_Arrays.asList
_ appelle en interne _new ArrayList
_, ce qui garantit l'inégalité de référence.
_List.of
_ dépend de la mise en œuvre interne. Les instances renvoyées peuvent avoir une égalité de référence, mais comme cela n’est pas garanti, vous ne pouvez pas vous en fier.
_asList1 == asList2; // false
listOf1 == listOf2; // true or false
_
Il est à noter que les listes sont égales (via List.equals
) si elles contiennent les mêmes éléments dans le même ordre, quelle que soit la façon dont elles ont été créées ou quelles opérations elles prennent en charge.
_asList.equals(listOf); // true i.f.f. same elements in same order
_
Si le nombre d'éléments dans la liste de _List.of
_ est inférieur ou égal à 2, les éléments sont stockés dans les 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 la même manière que _Arrays.asList
_.
Les implémentations _List.of
_ basées sur des champs (taille <2) sont légèrement plus rapides sur certaines opérations. Par exemple, size()
peut renvoyer une constante sans extraire la longueur du tableau, et contains(E e)
ne nécessite pas de surcharge d'itération.
Construire une liste non modifiable via _List.of
_ est également plus rapide. Comparez le constructeur ci-dessus avec 2 assignations de référence (et même celle pour une quantité 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 enregistrez le wrapper UnmodifiableList
ainsi que quelques sous. En fin de compte, les économies réalisées dans l’équivalent HashSet
sont plus convaincantes.
Conclusion time: utilisez _List.of
_ lorsque vous souhaitez une liste qui ne change pas et _Arrays.asList
_ lorsque vous souhaitez une liste pouvant être modifiée (comme indiqué ci-dessus).
Laissons résumer les différences entre List.of et Arrays.asList
Il est préférable d'utiliser List.of
lorsque le jeu de données est réduit et inchangé, tandis que Arrays.asList
peut être utilisé au mieux si le jeu de données est volumineux et dynamique.
List.of
prend très moins de temps système, car il a une implémentation basée sur le champ et consomme moins d’espace mémoire, à la fois en termes de temps système fixe et par élément. while Arrays.asList
prend plus de temps système car, lors de l’initialisation, il crée plus d’objets dans le tas.
La collection renvoyée par List.of
est immuable et donc thread-safe alors que la collection renvoyée par Arrays.asList
est mutable et non thread-safe. (Les instances de collection immuables consomment généralement beaucoup moins de mémoire que leurs homologues mutables.)
List.of
n'autorise pas null éléments tandis que Arrays.asList
autorise null éléments.