在Java中使用任意对象作为Map键的任何缺点?

我的应用程序中有两种对象,其中一种对象只有一种对应的对象。

跟踪这种关系的明显选择是Map ,就像HashMap一样。 但不知何故,我很怀疑。 我可以将一个对象用作Map中的一个键,传递它,让它坐在另一个集合中,并随时从Map中检索它的伙伴吗?

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

还有其他警告吗? 我应该使用其他东西来关联对象,就像我自己生成的数字一样吗?

  1. 关键需要正确实现.equals().hashCode()
  2. 密钥不得以任何方式更改, .hashCode()在将其用作密钥时更改其.hashCode()
  3. 理想情况下,在HashMap用作键的任何对象都应该是不可变的。 这将自动确保2.始终保持为真。
  4. 当它们用作键和/或值时,可能会保留可能以其他方式进行GC的对象。

我的应用程序中有两种对象,其中一种对象只有一种对应的对象。

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

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

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

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

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

顺便说一句,你不必重写equals和hashCode,除非你必须考虑一个对象的几个实例相等…

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

是的,这里没问题。

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

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

还有其他警告吗? 我应该使用其他东西来关联对象,就像我自己生成的数字一样吗?

至于警告,是的,当对象在Map中时,你不能改变任何会导致对象的hashCode改变的东西。

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

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

您重写hashcode,因为它需要与equals一致。 这样,您定义为等于哈希的对象相同。

失败点是哈希码和等于函数。 如果它们不能产生一致且正确的返回值,则Map将表现得很奇怪。 有效的Java有一个完整的部分,强烈推荐。

您可以考虑使用Google Collection的BiMap 。