web-dev-qa-db-fra.com

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

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);
_
88
user5908494

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]
133
ZhekaKozlov

Les différences entre 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);
_

Immutabilité structurelle (ou: non modifiable)

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.

Hostilité nulle

_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 nulls.

_listOf.contains(null);  // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null);  // allowed
_

Formulaire sérialisé

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.

Identité

_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
_

Mise en œuvre (avertissement: les détails peuvent changer d'une version à l'autre)

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_.

Efficacité du temps et de l'espace

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).

23
user1803551

Laissons résumer les différences entre List.of et Arrays.asList

  1. 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.

  2. 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.

  3. 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.)

  4. List.of n'autorise pas null éléments tandis que Arrays.asList autorise null éléments.

14
Mohit Tyagi