Question

Ai-je raison de supposer que si vous avez un objet qui est contenu dans un Java Set <> (ou une clé dans une carte <> pour cette matière), tous les champs qui sont utilisés pour déterminer l'identité ou la relation (via hashCode(), equals(), etc. compareTo()) ne peut être modifiée sans causer un comportement non spécifié pour les opérations sur la collecte? (Edit: comme allusion dans cette autre question )

(En d'autres termes, ces champs doivent être soit immuable, ou vous devez exiger de l'objet à supprimer de la collection, puis a changé, puis réinséré.)

La raison pour laquelle je demande est que je lisais le Guide de référence Hibernate Annotations __gVirt_NP_NN_NNPS<__ et il a un exemple où il y a un mais la classe HashSet<Toy> a des champs Toy et name qui sont mutable serial et sont également utilisés dans le calcul .. <=> . un drapeau rouge a explosé dans ma tête et je voulais juste vous assurer que je compris les implications.

Était-ce utile?

La solution

Le Javadoc dit Set

  

Remarque: Un grand soin doit être exercé si   objets mutables sont utilisés comme ensemble   é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   équivaut à des comparaisons alors que l'objet est   un élément de l'ensemble. Un cas particulier   de cette interdiction est que ce n'est pas   admissible pour un ensemble de contenir   lui-même comme un élément.

Cela signifie simplement que vous pouvez utiliser des objets mutables dans un ensemble, et même les changer. Vous devez vous assurer que le changement n'a pas d'impact de la façon dont le trouve les éléments HashSet. Pour hashCode(), cela nécessiterait pas de modifier les champs utilisés pour le calcul <=>.

Autres conseils

C'est exact, il peut causer des difficultés à localiser l'entrée de la carte. Officiellement, le comportement est indéfini, donc si vous l'ajoutez à un HashSet ou comme une clé dans une table de hachage, vous ne devriez pas le changer.

Oui, qui va provoquer de mauvaises choses se passent.

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

Dans un HashSet / HashMap, vous peut muter un objet contenu pour modifier les résultats de l'opération compareTo() - comparaison relative n'est pas utilisé pour localiser les objets. Mais ce serait fatale dans un TreeSet / TreeMap.

Vous pouvez également muter des objets qui sont à l'intérieur d'un IdentityHashMap - rien d'autre que l'identité de l'objet est utilisé pour localiser le contenu.

Même si vous pouvez faire ces choses avec ces qualifications, ils font votre code plus fragile. Et si quelqu'un veut changer à un TreeSet plus tard, ou ajouter ce champ mutable au hashCode / test d'égalité?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top