web-dev-qa-db-fra.com

Java Collections immuables

De documentation de Java 1.6 Collection Framework :

Les collections qui ne prennent en charge aucune opération de modification (telles que add, remove et clear) sont appelées non modifiables . [...] Les collections qui garantissent en outre qu'aucun changement dans l'objet Collection ne sera jamais visible sont appelées immuables .

Le deuxième critère me trouble un peu. Étant donné que la première collection est non modifiable, et en supposant que la référence de la collection d'origine ait été supprimée, quels sont les changements mentionnés à la deuxième ligne? S'agit-il des modifications des éléments contenus dans la collection, c'est-à-dire de l'état des éléments?

Deuxième question:
Pour qu'une collection soit immuable, comment peut-on fournir les garanties supplémentaires spécifiées? Si l'état d'un élément de la collection est mis à jour par un thread, suffit-il pour l'immuabilité que les mises à jour de l'état ne soient pas visibles sur le thread contenant la collection immuable?

Pour qu'une collection soit immuable, comment fournit-on les garanties supplémentaires spécifiées?

108
Bhaskar

Les collections non modifiables sont généralement des vues en lecture seule (wrappers) d'autres collections. Vous ne pouvez pas les ajouter, les supprimer ou les effacer, mais la collection sous-jacente peut changer.

Les collections immuables ne peuvent pas du tout être modifiées - elles n'enveloppent pas une autre - elles ont leurs propres éléments.

Voici une citation de goyave ImmutableList

Contrairement à Collections.unmodifiableList(Java.util.List<? extends T>), qui est une vue d'une collection séparée qui peut toujours changer, une instance de ImmutableList contient ses propres données privées et ne changera jamais.

En résumé, pour obtenir une collection immuable sur une collection mutable, vous devez copier ses éléments dans la nouvelle collection et interdire toutes les opérations.

148
Bozho

La différence est que vous ne pouvez pas avoir de référence à une collection immuable qui permet des modifications. Les collections non modifiables ne sont pas modifiables via cette référence, mais un autre objet peut pointer sur les mêmes données grâce auxquelles elles peuvent être modifiées.

par exemple.

List<String> strings = new ArrayList<String>();
List<String> unmodifiable = Collections.unmodifiableList(strings);
unmodifiable.add("New string"); // will fail at runtime
strings.add("Aha!"); // will succeed
System.out.println(unmodifiable);
84
Simon Nickerson
Collection<String> c1 = new ArrayList<String>();
c1.add("foo");
Collection<String> c2 = Collections.unmodifiableList(c1);

c1 est mutable (c'est-à-dire ni non modifiable ni immuable ).
c2 est non modifiable : il ne peut pas être modifié lui-même, mais si plus tard je change c1 alors ce changement sera visible dans c2.

Cela est dû au fait que c2 est simplement un wrapper autour de c1 et pas vraiment une copie indépendante. Guava fournit le ImmutableList interface et quelques implémentations. Ceux-ci travaillent en créant une copie de l’entrée (à moins que l’entrée ne soit une collection immuable).

Concernant votre deuxième question:

La mutabilité/immuabilité d'une collection ne dépend pas de la mutabilité/immuabilité des objets qu'elle contient. La modification d'un objet contenu dans une collection ne ne compte pas comme "modification de la collection" pour cette description. Bien sûr, si vous avez besoin d'une collection immuable, vous voulez aussi que celle-ci contienne également des objets immuables.

19
Joachim Sauer

Maintenant Java 9 a des méthodes d'usine pour les listes immuables, les ensembles, les cartes et les entrées Map.Entry.

Dans Java SE 8 et versions antérieures, nous pouvons utiliser des méthodes utilitaires de la classe Collections telles que unmodifiableXXX pour créer des objets Collection immuable.

Cependant, ces méthodes Collections.unmodifiableXXX sont une approche très fastidieuse et prolixe. Pour remédier à ces problèmes, Oracle corp a ajouté quelques méthodes utilitaires aux interfaces List, Set et Map.

maintenant dans Java 9: - Les interfaces de liste et de jeu ont une méthode "of ()" pour créer un objet immuable de liste ou de jeu immuable, vide ou non vide, comme indiqué ci-dessous:

Exemple de liste vide

List immutableList = List.of();

Exemple de liste non vide

List immutableList = List.of("one","two","three");
14
Vijay Gupta

Je pense que le point ici est que même si une collection est non modifiable, cela ne garantit pas qu'elle ne peut pas changer. Prenons l'exemple d'une collection qui supprime des éléments s'ils sont trop vieux. Non modifiable signifie simplement que l'objet contenant la référence ne peut pas la changer, pas qu'il ne puisse pas changer. Un bon exemple de ceci est la méthode Collections.unmodifiableList. Il retourne une vue non modifiable d'une liste. La référence de liste qui a été transmise à cette méthode est toujours modifiable et peut donc être modifiée par tout détenteur de la référence transmise. Cela peut entraîner des exceptions ConcurrentModificationException et d’autres mauvaises choses.

Immuable, signifie que la collection ne peut en aucun cas être modifiée.

Deuxième question: une collection immuable ne signifie pas que les objets contenus dans la collection ne changeront pas, mais simplement que la collection ne changera pas dans le nombre et la composition des objets qu'elle contient. En d'autres termes, la liste de références de la collection ne changera pas. Cela ne signifie pas que les éléments internes de l'objet référencé ne peuvent pas changer.

6
John B

Pure4J soutient ce que vous recherchez, de deux manières.

Tout d'abord, il fournit une annotation @ImmutableValue, afin que vous puissiez annoter une classe pour indiquer qu'elle est immuable. Il existe un plugin maven pour vous permettre de vérifier que votre code est réellement immuable (utilisation de final etc.).

Deuxièmement, il fournit les collections persistantes de Clojure (avec les génériques ajoutés) et garantit que les éléments ajoutés aux collections sont immuables. La performance de ceux-ci est apparemment très bonne. Les collections sont toutes immuables, mais implémentez Java interfaces de collections (et génériques) pour l'inspection. La mutation renvoie de nouvelles collections.

Disclaimer: Je suis le développeur de ce

0
Rob Moffat