在我的类的equals()方法中,我使用了一个私有实例HashMap变量来比较它们是否相等。然而,当比较它们的HashMap变量时,两个不同的对象仍然显示相等。进一步的研究将我带到这个链接:链接在此。然而,它只是说HashMap1.equals(HashMap2)不起作用的原因是,“显然Java的数组不能在没有编写定制代码的情况下测试它们的相等性。” 我不理解这个原因。是否有人可以向我解释得更详细些?
equals
方法等同于==
,因为Java数组“类”不会覆盖Object.equals
。如果要按值比较数组,需要使用适当的java.util.Arrays.equals(...)
方法或自己实现。如果您的HashMap
使用数组作为键或值,则它将调用数组的equals
方法来测试两个映射之间的键和/或值是否相同。这会使得HashMap.equals
行为奇怪(从您的角度来看)。但是,数组语义仅在将数组用作键或值类时才会影响HashMap
相等性。如果不是,则HashMap::equals
应该按预期工作。关于Map
类的相等性的javadoc有点复杂,但基本上可以归结为获取两个条目集,比较它们的大小,然后执行s1.containsAll(s2)
。当然,这很费时间,但应该对所有正确实现Map
接口的Map
类有效。equals
和hashCode
的语义与HashMap
不匹配。对于大多数用例,需要映射按值而不是按对象标识符比较键。
2. 数组是可变的。即使我们假定可以解决equals
/hashcode
问题,您仍然可以通过修改数组键来破坏映射的不变性。这篇文章是正确的。只要键对象和值对象可以使用相同的方法进行比较,就可以安全地使用equals()方法比较哈希映射。在文章中,映射值是数组,不像预期那样实现了equals()方法。使用ArrayList代替数组将解决此问题。
原生的Java数组没有 .equals() 函数。所以如果你的哈希表的值(或键)是数组,HashMap.equals() 将会失败。我猜测它会回退到 Object.equals(),它只检查这两个对象是否实际上是同一个对象。
// something like this
class Object {
public boolean equals( Object o) {
return this == o;
}
}
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()
方法时,集合内容执行的操作。