在我的类的equals()方法中,我使用私有实例HashMap变量来比较相等性。但是,在比较它们的HashMap变量时,2个不同的对象仍然显示相等。进一步的研究让我想到了这个链接:Link Here。但是,它只是说HashMap1.equals(HashMap2)无法工作的原因是因为“如果不编写自定义代码,就无法对Java的数组进行相同的测试。”
我不明白这个原因。任何人都可以指导我一个精心设计的理由吗?
答案 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
类。
请注意,使用数组作为地图的键是一个坏主意,原因有两个:
equals
数组hashCode
和HashMap
的语义都是错误的。对于大多数用例,您需要使用映射来按值而不是按对象标识比较键。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
不同方式的特殊情况,具体取决于它是否被覆盖。