Quelle est la différence entre List.of et Arrays.asList?

Java 9 a introduit de nouvelles méthodes Factory Collection, List.of :

 List ssortingngs = List.of("first", "second"); 

Alors, quelle est la différence entre les options précédentes et nouvelles? 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 mutable tandis que la liste renvoyée par List.of est immuable:

 List list = Arrays.asList(1, 2, null); list.set(1, 10); // OK List list = List.of(1, 2, 3); list.set(1, 10); // Fails 

Arrays.asList autorise les éléments null alors que List.of ne le fait pas:

 List list = Arrays.asList(1, 2, null); // OK List list = List.of(1, 2, null); // Fails with a NullPointerException 

contains méthode contains se comporte différemment avec des valeurs nulles:

 List list = Arrays.asList(1, 2, 3); list.contains(null); // Return false List list = List.of(1, 2, 3); list.contains(null); // Throws NullPointerException 

Arrays.asList renvoie une vue du tableau transmis, de sorte que les modifications apscopes au tableau seront également reflétées dans la liste. Pour List.of ce n’est pas vrai:

 Integer[] array = {1,2,3}; List list = Arrays.asList(array); array[1] = 10; System.out.println(list); // Prints [1, 10, 3] Integer[] array = {1,2,3}; List list = List.of(array); array[1] = 10; System.out.println(list); // Prints [1, 2, 3] 

Les différences entre Arrays.asList et List.of

Voir les JavaDocs et cette conférence de Stuart Marks (ou des versions précédentes).

Je vais utiliser les éléments suivants pour les exemples de code:

 List listOf = List.of(...); List asList = Arrays.asList(...); List unmodif = Collections.unmodifiableList(asList); 

Immutabilité structurelle (Ou: impossible à modifier)

Toute tentative de modification structurelle de List.of entraînera une List.of . Cela inclut les opérations telles que l’ ajout , la définition et la suppression . Vous pouvez toutefois modifier le contenu des objects de la liste (si les objects ne sont pas immuables), la liste n’est donc 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 changer si vous modifiez la liste d’origine.

Arrays.asList n’est pas complètement immuable, il n’a pas de ressortingction sur le 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 possédez) changera la liste.

L’immutabilité 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 en tant qu’élément. Si vous tentez de transmettre null en tant qu’élément ou même une recherche, vous NullPointerException une NullPointerException .

Arrays.asList étant une collection de 1.2 (le Framework Collections), il autorise null s null .

 listOf.contains(null); // NullPointerException unmodif.contains(null); // allowed asList.contains(null); // allowed 

Forme sérialisée

Comme List.of a été introduit dans Java 9 et que les listes créées par cette méthode ont leur propre forme sérialisée (binary), elles ne peuvent pas être désérialisées sur les versions antérieures de JDK (sans compatibilité binary ). Cependant, vous pouvez par exemple / sérialiser avec JSON.

Identité

Arrays.asList appelle en interne le new ArrayList , qui garantit une 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 y fier.

 asList1 == asList2; // false listOf1 == listOf2; // true or false 

Il convient de mentionner que les listes sont égales (via List.equals ) si elles contiennent les mêmes éléments dans le même ordre, indépendamment de la manière dont elles ont été créées ou des opérations qu’elles prennent en charge.

 asList.equals(listOf); // true iff same elements in same order 

Mise en œuvre (avertissement: les détails peuvent changer sur les versions)

Si le nombre d’éléments dans la liste de List.of est inférieur ou List.of 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 extends AbstractImmutableList { 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 manière similaire à Arrays.asList .

Efficacité temporelle et spatiale

Les implémentations List.of basées sur les champs (size <2) sont légèrement plus rapides sur certaines opérations. Comme exemples, size() peut renvoyer une constante sans aller chercher la longueur du tableau et contains(E e) ne nécessite pas de surcharge d’itération.

La construction d’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(...)); 

qui crée 2 listes plus d’autres frais généraux. En termes d’espace, vous enregistrez le wrapper UnmodifiableList et quelques sous. Au final, les économies réalisées dans l’équivalent de HashSet sont plus convaincantes.


Heure de conclusion: utilisez List.of lorsque vous voulez une liste qui ne change pas et Arrays.asList lorsque vous voulez une liste pouvant changer (comme indiqué ci-dessus).

Résumons les différences entre List.of et Arrays.asList

  1. List.of est préférable d’utiliser List.of lorsque le jeu de données est inférieur et inchangé, tandis que Arrays.asList peut être utilisé de manière optimale en cas de jeu de données volumineux et dynamic.

  2. List.of prend beaucoup moins de place sur la tête car il List.of implémentation basée sur les champs et consum moins d’espace de tas, à la fois en termes de surcharge fixe et d’éléments par élément. while Arrays.asList prend plus d’espace, car lors de l’initialisation, il crée davantage d’objects dans le tas.

  3. La collection renvoyée par List.of est immuable et donc sûre pour les threads, tandis que Collection retournée par Arrays.asList est mutable et non thread-safe. (Les instances de collection immuables consumnt généralement beaucoup moins de mémoire que leurs homologues mutables.)

  4. List.of n’autorise pas les éléments null alors Arrays.asList autorise les éléments null .