java.util.Set.contains(对象o)的怪异行为 [英] Weird behavior of java.util.Set.contains(Object o)
问题描述
doc 关于 java.util.Set.contains(Object o)
说:
当且仅当此集合包含元素e使得
(o == null?e == null:o.equals(e))时,返回true。
Returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
也就是说,这是一个POJO(如您所见,我重写了它的 equals
方法):
That said, here is a POJO (as you can see, I overwrote its equals
method):
public class MonthAndDay {
private int month;
private int day;
public MonthAndDay(int month, int day) {
this.month = month;
this.day = day;
}
@Override
public boolean equals(Object obj) {
MonthAndDay monthAndDay = (MonthAndDay) obj;
return monthAndDay.month == month && monthAndDay.day == day;
}
}
那么,为什么要执行以下操作代码显示 false
而不是 true
?
So please, why does the following code prints false
instead of true
?
Set<MonthAndDay> set = new HashSet<MonthAndDay>();
set.add(new MonthAndDay(5, 1));
System.out.println(set.contains(new MonthAndDay(5, 1)));
// prints false
一种解决方案是重写包含的内容(对象o)
方法,但是原始方法应该(几乎)完全一样,我错了吗?
A solution is to rewrite the contains(Object o)
method, but the original one should be (almost) exactly the same, am I wrong?
Set<MonthAndDay> set = new HashSet<MonthAndDay>() {
private static final long serialVersionUID = 1L;
@Override
public boolean contains(Object obj) {
MonthAndDay monthAndDay = (MonthAndDay) obj;
for (MonthAndDay mad : this) {
if (mad.equals(monthAndDay)) {
return true;
}
}
return false;
}
};
set.add(new MonthAndDay(5, 1));
System.out.println(set.contains(new MonthAndDay(5, 1)));
// prints true
推荐答案
equals(Object)
,您还需要覆盖 hashcode()
。
具体来说,必须实现这些方法,以便如果 a.equals(b)
为 true
,则 a.hashcode()== b.hashcode()
都是 true
。如果不遵守此不变式,则 HashMap
, HashSet
和 Hashtable
无法正常工作。
Specifically, the methods must be implemented so that if a.equals(b)
is true
, then a.hashcode() == b.hashcode()
is all true
. If this invariant is not respected, then HashMap
, HashSet
and Hashtable
will not work properly.
hashcode()
和的技术细节在对象中指定了equals(Object)
应该表现的行为 API。
The technical details of how hashcode()
and equals(Object)
should behave are specified in the Object API.
那么如果弄错了,为什么基于哈希的数据结构会中断?好吧,基本上是因为哈希表通过使用哈希函数的值来缩小要与候选进行比较的值的集合而起作用。如果候选人的哈希码与表中某个对象的哈希码不同,则即使对象相等,查找算法也可能无法与表中的对象进行比较。
So why do the hash-based data structures break if you get this wrong? Well basically because a hash table works by using the value of the hash function to narrow down the set of values to be compared with the "candidate". If the hashcode for the candidate is different to the hashcode for some object in the table, then the chances are that the lookup algorithm won't compare with the object in the table ... even if the objects are equal.
这篇关于java.util.Set.contains(对象o)的怪异行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!