在一个Java集对象可变域(mutable fields for objects in a Java

2019-06-24 20:23发布

我在假设,如果你有一个包含一个Java集<>内(或在地图<>对于这个问题的关键)的对象,所使用的任何字段,以确定身份或关系(通过正确hashCode()equals() compareTo()等)不能在没有对采集造成不确定的行为进行操作改变了吗? (编辑:在提到这个问题,其他 )

(换句话说,这些领域要么是不可变的,或者如果您需要将对象从集合中删除,然后改,然后重新插入。)

我要求的原因是,我正在读Hibernate标注参考指南 ,它有一个例子,其中有一个HashSet<Toy>Toy类有字段nameserial是可变的,并且在也用于hashCode()计算。 ..红旗在我的头上去了,我只是想确认我的理解它的含义。

Answer 1:

适用于Javadoc Set

注意:如果使用可变对象作为一组元素大,一定要小心。 如果一个对象的值以影响equals比较而对象是在该组的元素的方式改变一组的行为没有被指定。 这种禁止的特殊情况是,它是不允许的一组以自身作为一个元素。

这只是意味着你可以在一组使用可变对象,甚至改变他们。 你刚才应该确保更改不会影响的方式Set找到的项目。 对于HashSet ,这将需要不改变用于计算领域hashCode()



Answer 2:

这是正确的,它可能会导致一些问题,定位映射条目。 官方的行为是不确定的,所以如果你把它添加到HashSet或HashMap中的关键,你不应该改变它。



Answer 3:

是的,这会造成不好的事情发生。

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


Answer 4:

在一个HashSet / HashMap中,你可能会变异包含的对象来改变的结果compareTo()操作-相对比较不用于定位的对象。 但它会是一个TreeSet / TreeMap的内部致命的。

您也可以发生变异是一个IdentityHashMap中的对象 - 无非对象标识等用于定位的内容。

即使你可以做这些事情与这些资格,他们使你的代码更加脆弱。 如果有人想在以后改变到一个TreeSet,或可变的字段添加到的hashCode /平等的测试?



文章来源: mutable fields for objects in a Java Set