两个HashMap之间的相等性

25
在我的类的equals()方法中,我使用了一个私有实例HashMap变量来比较它们是否相等。然而,当比较它们的HashMap变量时,两个不同的对象仍然显示相等。进一步的研究将我带到这个链接:链接在此。然而,它只是说HashMap1.equals(HashMap2)不起作用的原因是,“显然Java的数组不能在没有编写定制代码的情况下测试它们的相等性。” 我不理解这个原因。是否有人可以向我解释得更详细些?
4个回答

33
Java数组类型的equals方法等同于==,因为Java数组“类”不会覆盖Object.equals。如果要按值比较数组,需要使用适当的java.util.Arrays.equals(...)方法或自己实现。如果您的HashMap使用数组作为键或值,则它将调用数组的equals方法来测试两个映射之间的键和/或值是否相同。这会使得HashMap.equals行为奇怪(从您的角度来看)。但是,数组语义仅在将数组用作键或值类时才会影响HashMap相等性。如果不是,则HashMap::equals应该按预期工作。关于Map类的相等性的javadoc有点复杂,但基本上可以归结为获取两个条目集,比较它们的大小,然后执行s1.containsAll(s2)。当然,这很费时间,但应该对所有正确实现Map接口的Map类有效。
请注意,将数组用作映射的键是一个糟糕的主意,原因有几个:
1. 在大多数情况下,数组equalshashCode的语义与HashMap不匹配。对于大多数用例,需要映射按值而不是按对象标识符比较键。 2. 数组是可变的。即使我们假定可以解决equals/hashcode问题,您仍然可以通过修改数组键来破坏映射的不变性。

11

这篇文章是正确的。只要键对象和值对象可以使用相同的方法进行比较,就可以安全地使用equals()方法比较哈希映射。在文章中,映射值是数组,不像预期那样实现了equals()方法。使用ArrayList代替数组将解决此问题。


4

原生的Java数组没有 .equals() 函数。所以如果你的哈希表的值(或键)是数组,HashMap.equals() 将会失败。我猜测它会回退到 Object.equals(),它只检查这两个对象是否实际上是同一个对象。

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

您可以使用容器的某个变体来规避问题,而不是使用array[],因为容器具有自己的.equals()方法,该方法会调用容器中连续元素的equals()方法,而不仅仅是检查它们是否是相同的引用。集合的.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()方法时,集合内容执行的操作。


1
数组继承自Object,并且具有与Object相同的实现。 - Peter Lawrey
这正是我所想的,尽管我没有费心去查。 - Mark Storer

2
Java的数组不能在没有编写自定义代码的情况下进行相等性测试。这只是说Java数组没有覆盖Object.equals()。因此,如果您使用equals()(这是所有集合类的equals方法所做的)进行比较,您将获得“实例相等”,而不是“值相等”。这实际上只是equals根据是否已被覆盖而工作的不同方式的特殊情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接