据我所知,==运算符用于参考比较,即两个对象是否指向相同的存储位置。 为了测试这个,我创建了一个小的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
}
}
需要理解为什么==运算符的行为在2和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;
}
}
答案 0 :(得分:1)
If the character is '@', all characters where isalpha() returns TRUE
are included. Normally these are the characters a to z and A to Z,
plus accented characters. To include '@' itself use "@-@".
比较两个变量但的引用这一事实是正确的,引用与哈希码不同。
哈希码是您编写的此方法返回的数字:
==
引用是存储对象的内存位置。它们完全不同。
你有这种误解是可以理解的。如果您没有覆盖@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;
}
,它将返回对象的内存位置,因此哈希代码将与内存位置相同。但是,由于您已覆盖hashCode
,因此它们不再相同。
答案 1 :(得分:0)
运算符==
检查两个引用是否指向内存中的同一对象(对于int
或double
运算符==
等基本类型检查相等的值。)
Employee a = new Employee(...);
Employee b = new Employee(...);
System.out.println(a == b); // false
System.out.println(b == a); // false
System.out.println(a == a); // true
System.out.println(b == a); // true
Employee c = b;
System.out.println(a == c); // the same as a == b
System.out.println(b == c); // the same as b == b
Object#equals(Object)
检查两个对象的内容是否相同。
Employee a = new Employee(1, "XYZ");
Employee b = new Employee(1, "XYZ");
// if Employee#equals(Object); is overridden so that,
// it checks both id and name for equality
// then we can expect that all these lines returns true
System.out.println(a.equals(b)); // true
System.out.println(b.equals(a)); // true
System.out.println(a.equals(a)); // true
System.out.println(b.equals(b)); // true
Employee c = b;
System.out.println(a.equals(c)); // this is the same as a.equlas(b);
Employee d = new Employee(2, "ABC");
System.out.println(a.equals(d)); // false
Object#hashCode()
返回标识内容的整数(如果两个对象相等,则哈希码必须相同)。
Employee a = new Employee(1, "XYZ");
Employee b = new Employee(1, "XYZ");
System.out.println(a.hashCode() == b.hashCode()); // true expected since a and b are equal
Employee c = b;
System.out.println(a.hashCode() == c.hashCode()); // the same as a.hashCode() == b.hashCode()
Employee d = new Employee(1, "xyz");
// might be false, but can be true,
// it all depends on quality of hashCode() implementation
System.out.println(a.hashCode() == d.hashCode());
在基于哈希的数据结构中使用 Hashcodes 来查找对象i的desination索引。即index索引存储对象的位置。假设Employee#hashCode()
为20
返回1, "XYZ"
。如果hashmap的基础数组的大小为11
,则目标索引将为20 modulo 11;
(9
)。因此,当您调用hashSet.contains(new Employee(1, "XYZ"));
时,它将查看索引9
。请注意,完美哈希函数会返回给定值的唯一编号不存在,也就是说,您的hashCode()
实现可能会返回编号{{ 1}}也用于属性值:20
(小写),它产生相同的哈希索引"1, "xyz"
。因此,在hashset在索引9
找到对象之后,它还必须执行相等性检查以确保存储在索引9
的对象等于在9
中传递的对象。