JavaBean,為什么要重寫hashCode()方法和equals()方法及如何重寫
JavaBean為什么要重寫hashCode()方法和equals方法,我記得當時我巴拉巴拉半天就是沒有說到重點.
現(xiàn)在想一想歸根到底還是我對這兩個的理解不深刻,現(xiàn)在我特定來總結(jié)下.hashCode 方法用于散列集合的查找,equals 方法用于判斷兩個對象是否相等。
一、我們?yōu)槭裁葱枰貙慼ashCode()方法和equals()方法?(Why)
有時在我們的業(yè)務系統(tǒng)中判斷對象時有時候需要的不是一種嚴格意義上的相等,而是一種業(yè)務上的對象相等。在這種情況下,原生的equals方法就不能滿足我們的需求了.
我們所知道的JavaBean的超類(父類)是Object類,JavaBean中的equals方法是繼承自Object中的方法.Object類中定義的equals()方法是用來比較兩個引用所指向的對象的內(nèi)存地址是否一致.并不是比較兩個對象的屬性值是否一致,所以這時我們需要重寫equals()方法.
Object類中equals()方法的源碼
public boolean equals(Object obj) {
return (this == obj);
}
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("awu",22);
Student stu2 = new Student("awu",22);
System.out.println(stu1.equals(stu2));
/*因為Student這個JavaBean沒有重寫關(guān)于屬性值相等的equals()方法
,所以默認比較的是地址值,從而輸出結(jié)果為false*/
}
}
那么為什么在重寫equals方法的時候需要重寫hashCode方法呢?
主要是Object.hashCode的通用約定:
在java應用程序運行時,無論何時多次調(diào)用同一個對象時的hsahCode()方法,這個對象的hashCode()方法的返回值必須是相同的一個int值. 如果兩個對象equals()返回值為true,則他們的hashCode()也必須返回相同的int值. 如果兩個對象equals()返回值為false,則他們的hashCode()返回值也必須不同.
以HashSet來說明為什么要這么約定:HashSet存放元素時,根據(jù)元素的hashCode值快速找到要存儲的位置,如果這個位置有元素,兩個對象通過equals()比較,如果返回值為true,則不放入;如果返回值為false,則這個時候會以鏈表的形式在同一個位置上存放兩個元素,這會使得HashSet的性能降低,因為不能快速定位了。
還有一種情況就是兩個對象的hashCode()返回值不同,但是equals()返回true,這個時候HashSet會把這兩個對象都存進去,這就和Set集合不重復的規(guī)則相悖了;所以,我們重寫了equals()方法時,要按照b,c規(guī)則重寫hashCode()方法!(其實就是如果只重寫了 equals 方法,兩個對象 equals 返回了true,但是如果沒有重寫 hashCode 方法,集合還是會插入元素。這樣集合中就出現(xiàn)了重復元素了。)
二、在什么情況下需要重寫hashCode()方法和equals()方法? (When)
當我們自定義的一個類,想要把它的實例保存在以Hash散列查找的集合中時,我們就需要重寫這兩個方法;
public class Student {
private String name;
private Integer age;
public Student(){
}
public Student(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int hashCode(){
final int prime = 31;
int result = 17;
result = prime * result + name.hashCode();
result = prime * result + age;
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
final Student other = (Student)obj;
if(name.equals(other.name)){
return false;
}
if(age.equals(other.age)){
return false;
}
return true;
}
}
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("awu",22);
Student stu3 = new Student("awu",33);
Student stu2 = new Student("awu",22);
Set set = new HashSet();
set.add(stu1);
set.add(stu2);
set.add(stu3);
System.out.println(set.size());
/*輸出結(jié)果為2*/
}
}
如果不是以Hash散列查找的集合,即使重寫HashCode也沒多大實際用處.比如如下栗子:
public class Demo {
public static void main(String[] args) {
Student stu1 = new Student("awu",22);
Student stu3 = new Student("awu",33);
Student stu2 = new Student("awu",22);
ArrayList list = new ArrayList();
list.add(stu1);
list.add(stu2);
list.add(stu3);
System.out.println(list .size());
/*輸出結(jié)果為3*/
}
}
三、如何重寫這兩個方法?(How)
public class Student {
private String name;
private Integer age;
public Student(){
}
public Student(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int hashCode(){
final int prime = 31;
int result = 17;
result = prime * result + name.hashCode();
result = prime * result + age;
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
final Student other = (Student)obj;
if(name.equals(other.name)){
return false;
}
if(age.equals(other.age)){
return false;
}
return true;
}
}
最近給大家找了 通用權(quán)限系統(tǒng)
資源,怎么領(lǐng)取?
掃二維碼,加我微信,回復:通用權(quán)限系統(tǒng)
注意,不要亂回復 沒錯,不是機器人 記得一定要等待,等待才有好東西
