Java Set 中对象的可变字段
我是否正确假设如果您有一个包含在 Java Set<> 中的对象? (或作为 Map<> 中的键),用于确定身份或关系的任何字段(通过 hashCode()
、equals()
、 compareTo()
等) 无法在不导致集合操作出现未指定行为的情况下进行更改吗? (编辑:正如 这个其他问题中提到的)
(换句话说,这些字段应该是不可变的,或者您应该要求从集合中删除对象,然后更改,然后重新插入。)
我问的原因是我正在阅读 Hibernate Annotations 参考指南 ,它有一个示例,其中有一个 HashSet
但Toy
类具有可变字段 name
和 serial
,也用于 hashCode()
计算。我的脑海中响起了一个危险信号,我只是想确保我理解它的含义。
Am I correct in assuming that if you have an object that is contained inside a Java Set<> (or as a key in a Map<> for that matter), any fields that are used to determine identity or relation (via hashCode()
, equals()
, compareTo()
etc.) cannot be changed without causing unspecified behavior for operations on the collection? (edit: as alluded to in this other question)
(In other words, these fields should either be immutable, or you should require the object to be removed from the collection, then changed, then reinserted.)
The reason I ask is that I was reading the Hibernate Annotations reference guide and it has an example where there is a HashSet<Toy>
but the Toy
class has fields name
and serial
that are mutable and are also used in the hashCode()
calculation... a red flag went off in my head and I just wanted to make sure I understood the implications of it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Set
的 javadoc 说这仅仅意味着您可以在集合中使用可变对象,甚至可以更改它们。 您只需确保更改不会影响
Set
查找项目的方式即可。 对于HashSet
,这不需要更改用于计算hashCode()
的字段。The javadoc for
Set
saysThis simply means you can use mutable objects in a set, and even change them. You just should make sure the change doesn't impact the way the
Set
finds the items. ForHashSet
, that would require not changing the fields used for calculatinghashCode()
.这是正确的,它可能会导致定位地图条目时出现一些问题。 官方的行为是未定义的,因此如果将其添加到哈希集或作为哈希映射中的键,则不应更改它。
That is correct, it can cause some problems locating the map entry. Officially the behavior is undefined, so if you add it to a hashset or as a key in a hashmap, you should not be changing it.
是的,这会导致不好的事情发生。
Yes, that will cause bad things to happen.
在 HashSet/HashMap 中,您可以改变所包含的对象来更改
compareTo()
操作的结果 - 相对比较不用于定位对象。 但在 TreeSet/TreeMap 中这将是致命的。您还可以改变 IdentityHashMap 内的对象——除了对象标识之外,没有其他任何东西用于定位内容。
尽管您可以通过这些资格来做这些事情,但它们会使您的代码更加脆弱。 如果有人想稍后更改为 TreeSet,或者将该可变字段添加到 hashCode/相等性测试中怎么办?
In a HashSet/HashMap, you could mutate a contained object to change the results of
compareTo()
operation -- relative comparison isn't used to locate objects. But it'd be fatal inside a TreeSet/TreeMap.You can also mutate objects that are inside an IdentityHashMap -- nothing other than object identity is used to locate contents.
Even though you can do these things with these qualifications, they make your code more fragile. What if someone wants to change to a TreeSet later, or add that mutable field to the hashCode/equality test?