Java Set 中对象的可变字段

发布于 2024-07-25 23:39:04 字数 701 浏览 10 评论 0原文

我是否正确假设如果您有一个包含在 Java Set<> 中的对象? (或作为 Map<> 中的键),用于确定身份或关系的任何字段(通过 hashCode()equals()compareTo() 等) 无法在不导致集合操作出现未指定行为的情况下进行更改吗? (编辑:正如 这个其他问题中提到的)

(换句话说,这些字段应该是不可变的,或者您应该要求从集合中删除对象,然后更改,然后重新插入。)

我问的原因是我正在阅读 Hibernate Annotations 参考指南 ,它有一个示例,其中有一个 HashSetToy 类具有可变字段 nameserial,也用于 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白云悠悠 2024-08-01 23:39:04

Set 的 javadoc 说

注意:如果出现以下情况,必须格外小心
可变对象作为集合使用
元素。 集合的行为不是
指定对象的值是否为
以影响的方式改变
equals 比较,而对象是
集合中的一个元素。 特殊情况
该禁令的主要内容是它不
一个集合允许包含
本身作为一个元素。

这仅仅意味着您可以在集合中使用可变对象,甚至可以更改它们。 您只需确保更改不会影响 Set 查找项目的方式即可。 对于 HashSet,这不需要更改用于计算 hashCode() 的字段。

The javadoc for Set says

Note: Great care must be exercised if
mutable objects are used as set
elements. The behavior of a set is not
specified if the value of an object is
changed in a manner that affects
equals comparisons while the object is
an element in the set. A special case
of this prohibition is that it is not
permissible for a set to contain
itself as an element.

This 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. For HashSet, that would require not changing the fields used for calculating hashCode().

对岸观火 2024-08-01 23:39:04

这是正确的,它可能会导致定位地图条目时出现一些问题。 官方的行为是未定义的,因此如果将其添加到哈希集或作为哈希映射中的键,则不应更改它。

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.

用心笑 2024-08-01 23:39:04

是的,这会导致不好的事情发生。

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

Yes, that will cause bad things to happen.

// 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
友欢 2024-08-01 23:39:04

在 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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文