6

我的应用程序中有两种对象,其中一种对象恰好有一个对应的另一种对象。

跟踪这种关系的明显选择是Map<type1, type2>,例如 HashMap。但不知何故,我很怀疑。我可以在 Map 中使用一个对象作为键,传递它,让它也放在另一个集合中,并随时从 Map 中检索它的伙伴吗?

创建对象后,我传递的只是一个标识符,对吗?所以那里可能没有问题。如果我序列化和反序列化密钥怎么办?

还有其他注意事项吗?我是否应该使用其他东西来关联对象对,例如我自己生成的数字?

4

8 回答 8

22
  1. 关键需要落实.equals().hashCode()正确
  2. 密钥在用作密钥时不得以任何改变其值的方式进行更改.hashCode()
  3. 理想情况下,任何用作 a 中的键的对象HashMap都应该是不可变的。这将自动确保 2. 始终为真。
  4. 否则可能会被 GC 处理的对象在用作键和/或值时可能会被保留。
于 2009-03-11T15:25:43.260 回答
7

我的应用程序中有两种对象,其中一种对象恰好有一个对应的另一种对象。

这听起来确实像一个有关系,因此可以使用一个简单的属性来实现。

于 2009-03-11T15:26:32.090 回答
3

这取决于您选择的地图的实现:

  • HashMap使用equals()hashCode()。默认情况下(在对象中),这些基于对象标识,除非您序列化/反序列化,否则它将正常工作。根据对象的内容正确实现 equals() 和 hashCode() 不会有任何问题,只要在它是哈希映射中的键时不对其进行修改。

  • TreeMap使用compareTo()。没有默认实现,因此您需要提供一个。与上面实现 hashCode() 和 equals() 的限制相同。

于 2009-03-11T15:30:37.743 回答
1

您可以使用标准 Map,但这样做会在 Map 中保留对对象的强引用。如果您的对象在另一个结构中被引用,并且您需要 Map 只是将它们链接在一起,请考虑使用 Wea​​kHashMap。

顺便说一句,除非您必须将对象的多个实例视为相等,否则您不必覆盖 equals 和 hashCode...

于 2009-03-11T15:28:11.757 回答
1

我可以在 Map 中使用一个对象作为键,传递它,让它也放在另一个集合中,并随时从 Map 中检索它的伙伴吗?

是的,这里完全没有问题。

创建对象后,我传递的只是一个标识符,对吗?所以那里可能没有问题。如果我序列化和反序列化密钥怎么办?

没错,您只是在传递一个引用——它们都将指向同一个实际对象。如果您序列化或反序列化对象,则会创建一个新对象。但是,如果您的对象正确实现了 equals 和 hashCode,您应该仍然能够使用新的反序列化对象从地图中检索项目。

还有其他注意事项吗?我是否应该使用其他东西来关联对象对,例如我自己生成的数字?

至于注意事项,是的,当对象在 Map 中时,您不能更改任何会导致对象的 hashCode 更改的内容。

于 2009-03-11T15:30:08.087 回答
0

任何对象都可以是映射键。这里重要的是确保为将用作映射键的任何对象覆盖 .equals() 和 .hashCode()。

这样做的原因是,如果不这样做,equals 将被理解为对象相等,并且您能够找到“相等”映射键的唯一方法是拥有原始对象本身的句柄。

您覆盖哈希码是因为它需要与 equals 一致。这是为了使您定义为 equals 的对象具有相同的哈希值。

于 2009-03-11T15:25:45.383 回答
0

故障点是 hashcode 和 equals 函数。如果它们不能产生一致且正确的返回值,则 Map 的行为会很奇怪。Effective Java有一个完整的章节,强烈推荐。

于 2009-03-11T15:25:56.630 回答
0

您可能会考虑 Google Collection 的BiMap

于 2009-03-11T15:35:50.257 回答