2 HashMap之间的平等

时间:2010-11-02 21:50:16

标签: java hashmap equals

在我的类的equals()方法中,我使用私有实例HashMap变量来比较相等性。但是,在比较它们的HashMap变量时,2个不同的对象仍然显示相等。进一步的研究让我想到了这个链接:Link Here。但是,它只是说HashMap1.equals(HashMap2)无法工作的原因是因为“如果不编写自定义代码,就无法对Java的数组进行相同的测试。”

我不明白这个原因。任何人都可以指导我一个精心设计的理由吗?

4 个答案:

答案 0 :(得分:31)

Java数组类型的equals方法等同于==,因为Java数组“类”不会覆盖Object.equals

如果要“按值”比较数组,则需要使用适当的java.util.Arrays.equals(...)方法,或自行实现。

如果您的HashHap使用数组作为键或值,那么它将调用数组的equals方法来测试两个映射之间的键和/或值是否相同。这会使HashMap.equals表现得很奇怪(从您的角度来看)。这就是链接文章所说的内容。但是,如果使用数组作为键或值类,则数组语义会影响HashMap相等性。如果不这样做,那么HashMap::equals应该按预期工作。

Map类的相等的javadoc有点涉及,但它们基本上归结为取两个入口集,比较它们的大小,然后做s1.containsAll(s2)。当然,这很昂贵,但应该适用于正确实现Map接口的所有Map类。


请注意,使用数组作为地图的键是一个坏主意,原因有两个:

  1. 在大多数情况下,equals数组hashCodeHashMap的语义都是错误的。对于大多数用例,您需要使用映射来按值而不是按对象标识比较键。
  2. 阵列是可变的。如果我们假设equals / hashcode问题有解决方法,您可以通过修改数组键仍然打破地图的不变量。

答案 1 :(得分:9)

文章是对的。只要可以使用相同的方法比较关键对象和值对象,就可以使用equals()方法安全地比较散列图。在本文中,映射值是数组,它们没有按预期实现equals()。相反,使用ArrayList可以解决问题。

答案 2 :(得分:4)

Native Java数组没有.equals()函数。因此,如果您的hashmap的值(或我认为的键)是数组,HashMap.equals()将失败。我怀疑它会回到Object.equals()上,它只是检查两个对象是否实际上是同一个对象。

// something like this
class Object {
  public boolean equals( Object o) {
    return this == o;
  }
}

你可以通过在Container而不是array []上使用一些变体来回避问题,因为容器有自己的.equals(),它在容器的连续元素上调用equals()而不是简单地检查它们是否是相同的参考。 Collection.equals实现的代码可能类似于:

public boolean equals(Object o) {
  // sets never equal lists and visa versa
  if (o instanceof MyCollectionSubclass) {
    Iterator myIterator = iterator();
    Iterator theirIterator = ((Collection)o).iterator();
    while (myIterator.hasNext() && theirIterator.hasNext()) {
      Object myObj = myIterator.next();
      Object theirObj = theirIterator.next();
      if (!myObj.equals(theirObj)) {
        return false;
      }
    }
    // at least one will be false or we wouldn't have left the above while loop
    return myIterator.hasNext() == theirIterator.hasNext();
  }
  // not our class
  return false;
}

这可能会产生真正的价值比较,具体取决于您在调用equals()时收集内容的内容。

答案 3 :(得分:2)

  

如果不编写自定义代码,就无法测试Java的数组

这只是一种复杂的说法,即Java数组不会覆盖Object.equals()。因此,如果使用equals()(这是所有集合类的equals方法)进行比较,则会得到“实例相等”,而不是“值相等”。

这只是equals不同方式的特殊情况,具体取决于它是否被覆盖。