12
votes

champs mutables pour les objets dans un ensemble Java

suis-je correct en supposant que si vous avez un objet contenu dans un ensemble Java <> (ou en tant que clé dans une carte <> pour cette matière), tous les champs utilisés pour déterminer l'identité ou la relation (via hashcode () , est égal () , comparète () etc.) ne peut pas être modifié sans causer un comportement non spécifié pour les opérations sur la collection? (Edit: Comme mentionné dans Cette autre question )

(En d'autres termes, ces champs doivent être immuables, ou si vous devez retirer l'objet de la collection, puis modifié, puis réinséré.)

La raison pour laquelle je demande est que je lisais le Hibernate Annotations Guide de référence et il a un exemple où il existe un hashset mais la classe jouet classes a champs nom et série qui sont mutables et sont également utilisés dans le hashcode () Calcul ... Un drapeau rouge s'est éteint dans ma tête et je voulais juste m'assurer que j'ai compris les implications de celui-ci.


0 commentaires

4 Réponses :


3
votes

C'est correct, cela peut entraîner des problèmes de localisation de l'entrée de la carte. Officiellement, le comportement est indéfini, donc si vous l'ajoutez à un hashset ou en tant que clé dans un hashmap, vous ne devez pas le changer.


0 commentaires

1
votes

Oui, cela entraînera des choses graves.

// Given that the Toy class has a mutable field called 'name' which is used
// in equals() and hashCode():
Set<Toy> toys = new HashSet<Toy>();
Toy toy = new Toy("Fire engine", ToyType.WHEELED_VEHICLE, Color.RED);
toys.add(toy);
System.out.println(toys.contains(toy)); // true
toy.setName("Fast truck");
System.out.println(toys.contains(toy)); // false


3 commentaires

Attendez, je viens de réaliser que c'était un exemple vraiment mauvais. Puisque j'ai toujours eu la référence de la référence, la dernière contient () retournera en fait vrai. Les hachemaps sont une question différente, mais cela quitte presque l'heure sur un week-end de trois jours et je ne veux pas creuser un exemple.


heh, postez quelque chose quand vous revenez - j'attends-le avec impatience.


Attendez de nouveau, j'ai oublié que Hashset utilise un haschmap comme support. Cela pourrait bien se produire: le hachemap de support utilise le hashcode pour sauter sur un seau avant de vérifier l'équivalent () sur les éléments du seau et la modification d'un élément le fera de sauter au mauvais godet et de ne pas trouver aucun élément là-bas.



8
votes

Le javadoc pour définir dit

Note: Les grands soins doivent être exercés si Les objets mutables sont utilisés comme défini éléments. Le comportement d'un ensemble n'est pas spécifié si la valeur d'un objet est changé d'une manière qui affecte égale les comparaisons tandis que l'objet est un élément dans l'ensemble. Un cas particulier de cette interdiction est que ce n'est pas Permissible pour un ensemble de contenir elle-même comme un élément.

Cela signifie simplement que vous pouvez utiliser des objets mutables dans un ensemble et même les changer. Il suffit de vous assurer que le changement n'a pas d'impact sur la manière dont le fichier trouve les éléments. Pour hashset , cela nécessiterait de ne pas modifier les champs utilisés pour calculer hashcode () .


0 commentaires

0
votes

dans un hashset / hashmap, vous pourrait Mutater un objet contenu pour modifier les résultats de comparète () Opération - La comparaison relative n'est pas utilisée pour localiser les objets. Mais ce serait fatal à l'intérieur d'un arbre / preemap.

Vous pouvez également transformer des objets qui sont à l'intérieur d'une identitéHashmap - rien d'autre que l'identité d'objet sert à localiser le contenu.

Même si vous pouvez faire ces choses avec ces qualifications, elles rendent votre code plus fragile. Et si quelqu'un veut changer d'arbres plus tard, ou ajoutez ce champ mutable au test HashCode / Équilibre?


0 commentaires