Java 2 HashMap 之间的相等性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4082416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Equality between 2 HashMap
提问by name_masked
In the equals() method of my class, I am using a private instance HashMap variable to compare for the equality. However, 2 different objects still show being equal when comparing their HashMap variables. Further research brought me to the link : Link Here. However, it just says that the reason for HashMap1.equals(HashMap2) not working is because " apparantly Java's arrays cannot be tested for equality without writing a customized code."
在我的类的 equals() 方法中,我使用私有实例 HashMap 变量来比较相等性。但是,在比较它们的 HashMap 变量时,2 个不同的对象仍然显示相等。进一步的研究将我带到了链接:Link Here。但是,它只是说 HashMap1.equals(HashMap2) 不起作用的原因是因为“显然,如果不编写自定义代码,就无法测试 Java 的数组是否相等。”
I did not understand this reason. Can anyone please guide me to a elaborate reason?
我不明白这个原因。任何人都可以指导我详细说明原因吗?
采纳答案by Stephen C
The equals
method on a Java array type is equivalent to ==
, because Java array "classes" do not override Object.equals
.
equals
Java 数组类型上的方法等效于==
,因为 Java 数组“类”不会覆盖Object.equals
。
If you want to compare arrays "by value" you need to either use the appropriate java.util.Arrays.equals(...)
method, or implement it yourself.
如果您想“按值”比较数组,您需要使用适当的java.util.Arrays.equals(...)
方法,或者自己实现。
If your HashMap
uses arrays as keys or values, then it is going to call the array's equals
method to test if the keys and/or values are the same between two maps. This would make HashMap.equals
behave strangely (from your perspective). That is what the linked article is saying. However, array semantic onlyaffect HashMap
equality if you use arrays as the key or value classes. If you don't, then HashMap::equals
should just work as expected.
如果您HashMap
使用数组作为键或值,那么它将调用数组的equals
方法来测试两个映射之间的键和/或值是否相同。这会使HashMap.equals
行为变得奇怪(从您的角度来看)。这就是链接文章所说的。但是,如果您使用数组作为键或值类,则数组语义仅影响HashMap
相等性。如果你不这样做,那么HashMap::equals
应该按预期工作。
The javadocs for equality on Map
classes are a bit involved, but they basically boil down to taking the two entry sets, comparing their sizes, and then doing s1.containsAll(s2)
. Of course, this is expensive, but it shouldwork for all of the Map
classes that correctly implement the Map
interface.
关于Map
类相等的 javadocs有点涉及,但它们基本上归结为获取两个条目集,比较它们的大小,然后执行s1.containsAll(s2)
. 当然,这很昂贵,但它应该适用于所有Map
正确实现Map
接口的类。
Note that using arrays as keys for maps is a bad idea for a couple of reasons:
请注意,由于以下几个原因,使用数组作为映射的键是一个坏主意:
- The semantics of array
equals
andhashCode
are wrong for aHashMap
in most scenarios. For most use-cases, you need the map to compare the keys by value not by object identity. - Arrays are mutable. If we assumed that there was a workaround for the
equals
/hashcode
problem, you could stillbreak a map's invariants by modifying an array key.
- 在大多数情况下,array
equals
和hashCode
a的语义是错误的HashMap
。对于大多数用例,您需要映射按值而不是对象标识来比较键。 - 数组是可变的。如果我们假设
equals
/hashcode
问题有解决方法,您仍然可以通过修改数组键来破坏映射的不变量。
回答by Mark Storer
Native Java arrays don't have a .equals() function. So if your hashmap's values (or keys I suppose) are arrays, HashMap.equals() will fail. I suspect it'd fall back on Object.equals() which just checks to see if the two objects are actually the same object.
本机 Java 数组没有 .equals() 函数。因此,如果您的 hashmap 的值(或我认为的键)是数组,则 HashMap.equals() 将失败。我怀疑它会回到 Object.equals() 上,它只是检查两个对象是否实际上是同一个对象。
// something like this
class Object {
public boolean equals( Object o) {
return this == o;
}
}
You can sidestep the problem by using some variant on a Container rather than an array[], as containers have their own .equals() which calls equals() on successive elements of the containers rather than simply checking if they're the same reference. The code for a Collection.equals implementation might look something like:
您可以通过在容器上使用一些变体而不是数组 [] 来回避这个问题,因为容器有自己的 .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;
}
This might produce a true value comparison depending on what the collection's contents do when you call their equals()
.
这可能会产生真正的值比较,具体取决于您调用它们的equals()
.
回答by Eyal Schneider
The article is right. Hashmaps can be safely compared using the equals() method as long as the key objects and value objects are possible to compare using the same method. In the article, the map values are arrays, which do not implement equals() as expected. Using ArrayList instead would have solved the problem.
文章是对的。只要可以使用相同的方法比较键对象和值对象,就可以使用 equals() 方法安全地比较哈希图。在文章中,map 值是数组,并没有按预期实现 equals()。改用 ArrayList 可以解决这个问题。
回答by sleske
Java's arrays cannot be tested for equality without writing a customized code
不编写自定义代码就无法测试 Java 的数组是否相等
This is just a complicated way of saying that Java arrays do not override Object.equals()
. Hence if you compare them using equals()
(which is what the equals
methods of all the collection classes do), you get "instance equality", instead of "value equality".
这只是一种复杂的说法,即 Java 数组不会覆盖Object.equals()
. 因此,如果您使用equals()
(这是equals
所有集合类的方法所做的)比较它们,您将获得“实例相等”,而不是“值相等”。
That's really just a special case of the different ways equals
works depending on whether it has been overridden or not.
这实际上只是不同方式equals
工作的一个特例,具体取决于它是否已被覆盖。