Object-1:
Employee employee1 = new Employee("AB12","Dhruv", 24);
Object-2:
Employee employee2 = new Employee("AB12", "Dhruv", 24);
输出
HASH CODE FOR EMPLOYEE 1 : 43704527
HASH CODE FOR EMPLOYEE 2 : 158893348
从https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--看以下几点
现在,看下面的代码及其输出:
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
输出:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
false
employee2.hashCode(): 1297685781
由于employee3
指向与employee1
相同的对象,所以当employee2
指向不同的对象时,它们将获得相同的哈希码(尽管其内容相同,关键字new
将在内存中创建一个单独的对象),因此,您很少会从文档状态中获得与上述point#4相同的employee2
哈希码:As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
您必须以一种方式重写hashCode
方法,该方法应为例如具有相同内容的两个对象返回相同的哈希码。
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
输出:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
false
employee2.hashCode(): 128107556
即使hashCode
返回employee1
,上面给出的employee2
的实现也会为equals
和false
产生相同的哈希码(请从文档中以上述[[point#3进行检查)。
hashCode
的错误覆盖方法可能导致即使相同的对象也返回不同的哈希码,例如class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : (int) (code.length() * (Math.random() * 100)));
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee1.hashCode() again: " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
输出:
true
employee1.hashCode(): 66066760
employee1.hashCode() again: 66069457
employee3.hashCode(): 66073797
false
employee2.hashCode(): 66074882
这是覆盖文档)。现在,看下面的代码及其输出:hashCode
的错误方法,因为在Java应用程序执行期间多次调用同一对象上的hashCode
必须一致地返回相同的整数(请检查上述point#1
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEmployee other = (MyEmployee) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
输出:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
true
employee2.hashCode(): 1297685781
由于employee1.equals(employee2)
返回true
,所以哈希码也应返回相同的值(请检查文档中的上述point#2
)。但是,employee1
和employee2
的哈希码值不同,这是不正确的。这种差异是因为我们没有重写hashCode
方法。因此,每当您覆盖equals
时,还应该以正确的方式覆盖hashCode
。最后,下面给出的是实现hashCode
和equals
的正确方法:class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
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;
MyEmployee other = (MyEmployee) obj;
if (age != other.age)
return false;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
输出:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
true
employee2.hashCode(): 128107556
亲切的问候,Arvind Kumar Avinash
@Override
hashCode()
方法并实现自己的版本,否则您的类将使用从Object
继承的默认方法,该方法将生成唯一的hashCode 每个对象实例。
如果您只想equals
和/或hashCode
只关心对象的成员,则需要自己编写实现。hashCode
来替换默认实现。覆盖equals
不会更改hashCode
(如果您覆盖equals
,几乎总是必须覆盖两者)。[hashCode
documentation这样说是关于Object
中的默认实现的:
在合理可行的范围内,Object类确实为不同的对象返回不同的整数。 (这个通常通过转换内部地址来实现对象转换成整数,但是这种实现技术不是Java™编程语言需要。)
因此,对于不同的实例,即使它们是等效的,也会得到不同的整数(通常),除非您替换hashCode
。
您可以这样操作
@Override
public int hashCode() {
return hashId;
}