À partir de la documentation de Java 1.6 Collection Framework :
Les collections qui ne prennent en charge aucune opération de modification (comme
add
,remove
etclear
) 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 déroute un peu. Étant donné que la première collection n'est pas modifiable, et en supposant que la référence de collection d'origine a été supprimée, quels sont les changements auxquels il est fait référence dans la deuxième ligne? Se réfère-t-il aux changements des éléments contenus dans la collection, c'est-à-dire à l'état des éléments?
Deuxième question:
pour qu'une collection soit immuable, comment faire pour fournir les garanties supplémentaires spécifiées? Si l'état d'un élément de la collection est mis à jour par un thread, est-il suffisant pour l'immuabilité que ces mises à jour de l'état ne soient pas visibles sur le thread contenant la collection immuable?
Pour qu'une collection soit immuable, comment procède-t-on pour fournir les garanties supplémentaires spécifiées?
la source
newCol = oldCol.add("element")
produira une nouvelle collection qui est une copie de l'ancienne avec 1 élément supplémentaire, et toutes les références à laoldCol
pointeront toujours vers la même ancienne collection inchangée.Réponses:
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 collection - elles ont leurs propres éléments.
Voici une citation de goyave
ImmutableList
Donc, fondamentalement, pour extraire une collection immuable d'une collection mutable, vous devez copier ses éléments dans la nouvelle collection et interdire toutes les opérations.
la source
unmodifiableList
, le code qui ne reçoit qu'une référence à cette liste ne pourra pas la modifier, mais tout code qui avait une référence à la liste d'origine et pourrait la modifier avant la création de l'encapsuleur sera toujours pouvoir le faire par la suite. Si le code qui a créé la liste originale sait ce qui est arrivé à chaque référence qui y a jamais existé, et sait qu'aucune d'elles ne tombera entre les mains d'un code susceptible de modifier la liste, alors il peut savoir que la liste ne sera jamais modifié. Si la référence a été reçue d'un code extérieur, cependant ...unmodifiableList
, ni pour aucun code qui l'utilise, de savoir si ou comment la collection encapsulée peut changer.La différence est que vous ne pouvez pas avoir de référence à une collection immuable qui autorise les modifications. Les collections non modifiables ne sont pas modifiables via cette référence , mais un autre objet peut pointer vers les mêmes données par lesquelles il peut être modifié.
par exemple
la source
c1
est mutable (c'est-à-dire ni non modifiable ni immuable ).c2
est non modifiable : il ne peut pas être changé lui - même, mais si plus tard je changec1
alors que le changement sera visible dansc2
.C'est parce qu'il
c2
s'agit simplement d'un wrapperc1
et pas vraiment d'une copie indépendante. Guava fournit l'ImmutableList
interface et certaines implémentations. Ceux-ci fonctionnent en créant une copie de l'entrée (à moins que l'entrée ne soit une collection immuable en elle-même).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 compte pas comme une "modification de la collection" pour cette description. Bien sûr, si vous avez besoin d'une collection immuable, vous souhaitez généralement qu'elle contienne des objets immuables.
la source
c1
n'échappe pas" n'est pas une considération qui se distingue n'importe où dans la spécification. À mon avis, si vous pouvez utiliser la collection d'une manière qui la rend non immuable, vous devriez toujours la considérer comme non immuable.Collection.unmodifiableList()
ne peut pas garantir cela, car il ne peut garantir que son argument n'échappe pas. Guava produitImmutableList.of
toujours un immuableList
, même si vous laissez échapper ses arguments.Maintenant, java 9 a des méthodes d'usine pour Immutable List, Set, Map et Map.Entry.
Dans Java SE 8 et les versions antérieures, nous pouvons utiliser des méthodes utilitaires de 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 verbeuse. Pour surmonter ces lacunes, Oracle corp a ajouté quelques méthodes utilitaires aux interfaces List, Set et Map.
Maintenant dans java 9: - Les interfaces List et Set ont des méthodes "of ()" pour créer une liste immuable ou des objets Set vide ou non vide comme indiqué ci-dessous:
Exemple de liste vide
Exemple de liste non vide
la source
List.copyOf
etSet.copyOf
ont été ajoutés qui permettent de créer une copie non modifiable d'une liste / ensemble, ou de renvoyer la collection donnée si elle est déjà non modifiable, voir JDK-8191517Je crois 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 par exemple une collection qui expulse des éléments s'ils sont trop anciens. Non modifiable signifie simplement que l'objet contenant la référence ne peut pas le changer, pas qu'il ne peut pas changer. Un vrai exemple de ceci est la
Collections.unmodifiableList
méthode. Il renvoie une vue non modifiable d'une liste. La référence List qui a été transmise à cette méthode est toujours modifiable et la liste peut donc être modifiée par n'importe quel détenteur de la référence qui a été transmise. Cela peut entraîner des exceptions ConcurrentModificationExceptions et d'autres problèmes.Immuable, signifie qu'en aucun cas la collection ne peut être modifiée.
Deuxième question: une collection immuable ne signifie pas que les objets contenus dans la collection ne changeront pas, mais que cette collection ne changera pas dans le nombre et la composition des objets qu'elle contient. En d'autres termes, la liste des 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.
la source
unmodifiableList
modifiée. Si vous souhaitez faire cela, utilisezImmutableList
.Pure4J prend en charge ce que vous recherchez, de deux manières.
Premièrement, il fournit une
@ImmutableValue
annotation, de sorte que vous pouvez annoter une classe pour dire qu'elle est immuable. Il existe un plugin maven pour vous permettre de vérifier que votre code est réellement immuable (utilisation definal
etc.).Deuxièmement, il fournit les collections persistantes de Clojure (avec des génériques ajoutés) et garantit que les éléments ajoutés aux collections sont immuables. La performance de ceux-ci est apparemment assez bonne. Les collections sont toutes immuables, mais implémentent des interfaces de collections Java (et des génériques) pour l'inspection. Mutation renvoie de nouvelles collections.
Avertissement: je suis le développeur de ce
la source