在Java中使用==运算符进行对象比较
据我所知,==运算符用于引用比较,即两个对象是否指向相同的内存位置。 为了测试这一点,我创建了一个小型java程序,但结果并不一致。有人对此有任何线索吗
import java.util.HashSet;
import java.util.Set;
public class EqualOperatorTest {
public static void main(String[] args) {
boolean result;
Employee employee1 = new Employee();
employee1.setId(1);
employee1.setName("XYZ");
Employee employee2 = new Employee();
employee2.setId(1);
employee2.setName("XYZ");
result = employee1.equals(employee2);
System.out.println("Comparing two different Objects with equals() method: " + result); //1. This returns True. Ok as we have overridden equals
result = (employee1 == employee2);
System.out.println("Comparing two different Objects with == operator: " + result); //2. This returns False. Why? hashcode of both employee1 and employee2 are same but still == comparison returning false.
//3. Validating hashcode of reference variables employee1 and employee2. We can see both has same hashcode (bcos we have overridden hashcode too in Employee class). But then why above employee1 == employee2 is returning false. Afterall == compares the memory location (or hashcode) and both have the same hashcodes,
System.out.println("employee1 : " + employee1); //employee1 and employee2 has same hashcode
System.out.println("employee2 : " + employee2); //employee1 and employee2 has same hashcode
// Creating hashset and storing the same employee references.
Set empSet = new HashSet();
empSet.add(employee1);
empSet.add(employee2);
System.out.println(empSet); //returns only one memory location(hashcode) as we have overridden hashcode in Employee class. Ok
employee1 = employee2; //Setting employee2 in employee1
result = (employee1 == employee2);
System.out.println("Comparing two reference pointing to same Object with == operator: " + result); //This returns True. Ok
}
}
Need to understand why behavior of == operator is not same at 2 and 3.
我的Employee类很简单,有两个类级变量,它们是getter和setter,以及重写的equals和hashcode方法
public class Employee {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@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 (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
# 1 楼答案
运算符
==
检查两个引用是否指向内存中的同一对象(对于诸如int
或double
之类的基元类型,运算符==
检查值是否相等)Object#equals(Object)
检查两个对象的内容是否相同Object#hashCode()
返回标识内容的整数(如果两个对象相等,则哈希代码必须相同)哈希代码用于基于哈希的数据结构中查找对象的指定索引,即存储对象的索引。假设
Employee#hashCode()
为1, "XYZ"
返回20
。如果hashmap的基础数组的大小为11
,则目标索引将为20 modulo 11;
(9
)。因此,当您调用hashSet.contains(new Employee(1, "XYZ"));
时,它将查看索引9
。注意,完美散列函数为给定值返回总是唯一的数字并不存在也就是说,您的hashCode()
实现也可能为属性值返回数字20
:"1, "xyz"
(小写),这将导致相同的散列索引9
。因此,在hashset在索引9
处找到对象之后,它还必须执行相等性检查,以确保存储在索引9
处的对象等于在contains(Object)
中传递的对象# 2 楼答案
关于
==
比较两个变量的引用这一事实,您是对的,但是,引用与哈希代码不同哈希代码是您编写的此方法返回的数字:
而引用是存储对象的内存位置。他们完全不同
你有这种误解是可以理解的。如果没有重写
hashCode
,它将返回对象的内存位置,因此哈希代码将与内存位置相同。但是,由于您已经重写了hashCode
,因此它们不再相同