在Java中使用任意对象作为映射键有什么缺点吗?

在Java中使用任意对象作为映射键有什么缺点吗?,java,collections,maps,Java,Collections,Maps,在我的应用程序中有两种对象,其中一种对象的每个对象都有一个对应的另一种对象 跟踪这种关系的明显选择是映射,就像HashMap一样。但不知怎么的,我很怀疑。我可以在地图中使用一个对象作为键,传递它,让它也位于另一个集合中,并随时从地图中检索它的伙伴吗 创建对象后,我传递的只是一个标识符,对吗?所以可能没问题。如果我序列化和反序列化密钥呢 还有其他注意事项吗?我是否应该使用其他东西来关联对象对,比如我自己生成的数字 该键需要正确实现.equals()和.hashCode() 当密钥用作密钥时,不得以

在我的应用程序中有两种对象,其中一种对象的每个对象都有一个对应的另一种对象

跟踪这种关系的明显选择是
映射
,就像HashMap一样。但不知怎么的,我很怀疑。我可以在地图中使用一个对象作为键,传递它,让它也位于另一个集合中,并随时从地图中检索它的伙伴吗

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

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

  • 该键需要正确实现
    .equals()
    .hashCode()
  • 当密钥用作密钥时,不得以任何方式更改其
    .hashCode()
  • 理想情况下,
    HashMap
    中用作键的任何对象都应该是不可变的。这将自动确保2。事实总是如此
  • 当它们被用作键和/或值时,可能会被GCed的对象可能会被保留

  • 任何对象都可以是贴图键。这里最重要的一点是确保为任何将用作映射键的对象重写.equals()和.hashCode()

    这样做的原因是,如果不这样做,相等将被理解为对象相等,而找到“相等”贴图关键点的唯一方法是拥有原始对象本身的句柄


    重写hashcode是因为它需要与equals保持一致。这使得您定义为equals的对象的散列相同。

    失败点是hashcode和equals函数。如果它们不能生成一致且正确的返回值,则映射的行为将异常。有一个完整的章节介绍它们,并且是非常非常推荐的

    我的房间里有两种东西 应用程序,其中每个对象 kind正好有一个对应的 另一种物体


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

    您可以使用标准贴图,但这样做会在贴图中保留对对象的强引用。如果你的对象被引用在另一个结构中,而你需要把它们链接在一起的地图,考虑使用一个弱小地图。< /P> 和btw,您不必重写等值和hash码,除非您必须将对象的几个实例视为相等…

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

    是的,这里一点问题都没有

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

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

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


    至于警告,是的,当对象在映射中时,不能更改任何会导致对象的哈希代码更改的内容

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

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

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


    你可以考虑谷歌的集合。不过,问题的其余部分可能对其他人仍然有用。(或者甚至对于@OP,如果出于某种原因这不是一个替代方案的话)@saua,我同意你的看法。我只是想指出属性在这个特定上下文中的适用性。