在阅读equals()和hashcode()时,我开始知道如果两个对象相等,那么它们的哈希码必须相等,但反之亦然。
但是下面的例子没有反映这一点。
class Employee{
private String name;
Employee(String name){
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
现在,如果我创建两个Employee对象
Employee e1 = new Employee("hi");
Employee e2 = new Employee("hi");
如果我这样做,e1.equals(e2)
,它会返回 true ,即使它们的哈希码不同,这在打印时很明显,e1.hashcode()
和e2.hashcode()
。
有人可以解释一下吗?
答案 0 :(得分:10)
您需要覆盖hashcode
方法并提供与equals签订合同的实现。
@Override
public int hashCode() {
return name == null ? 0 : name.hashCode();
}
equals
,则必须覆盖hashCode
equals
和hashCode
必须use the same
set of fields
equal
,则其hashCode
值必须为equal
井immutable
,则hashCode
是缓存的候选对象
和lazy initialization
您可以阅读有关实施哈希码here
的信息如果不覆盖该方法,将使用Object类中的默认行为。
尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数。 (这通常通过将对象的内部地址转换为整数来实现,但JavaTM编程语言不需要此实现技术。)
基于哈希的[HashMap,HashSet,Hashtable,LinkedHashSet,WeakHashMap]
集合将使用hashCode()
在存储桶中查找/存储对象,然后他们将调用equals()
。
答案 1 :(得分:4)
这是因为,每次覆盖equals
方法时,您还必须覆盖hashcode
方法。
否则,您的对象将根据您的代码进行比较,但它们的HashCode将根据Object类中的预定义算法进行计算。
注意: - 一般而言,您在检查objects
是否等于时考虑了所有参数,您应该使用all those parameters
来计算{{1}每个hashcodes
。
请参阅this very good post,其中介绍了object
和equals
方法的使用。
从这篇文章中引用一行,我已经在上面描述过: -
使用同一组字段来计算您在
hashcode
方法中使用的hashcode
让我们看看下面的Demo来理解上面的陈述: -
equals
所以,如果两个对象具有相同的public class Demo {
private String str;
private String name;
public boolean equals(Object obj) {
// Suppose you compare two objects based on length of their name variable
// If name equals, object are equal
if (obj instanceof Demo) {
return this.name.equals(((Demo)obj).name);
}
return false;
}
// ****** Badly Overrided hashcode *******
public int hashcode() {
// But you calculate hashcode using both the fields
// You should never use this kind of code in hashcodes.
// Use complex algorithm which gives you distinct result for
// objects that are not equal.
return str.length + name.length;
}
}
,那么它们将是相同的,但如果它们的name
字段具有不同的str
,那么它们的length
将是不同。
这就是为什么你应该总是在hashcodes
和same fields
计算中使用equals
。
答案 2 :(得分:0)
您还需要覆盖hashCode
以获得您期望的行为。 Object.hashCode
的默认实现可能会返回对象引用,但根据the docs,这不是必需的。
如果不覆盖hashCode
,你就不能指望专门的结果;这类似于覆盖equals
。
答案 3 :(得分:0)
你应该覆盖hashcode方法。 如果一个类重写equals,它必须覆盖hashCode 当它们都被重写时,equals和hashCode必须使用相同的字段集 如果两个对象相等,那么它们的hashCode值也必须相等 如果对象是不可变的,则hashCode是缓存和延迟初始化的候选者