【09期】說說hashCode() 和 equals() 之間的關系?
閱讀本文大概需要 6 分鐘。
來自:java面試題精選

介紹
equals()?的作用是用來判斷兩個對象是否相等。hashCode()?的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數(shù)。這個哈希碼的作用是確定該對象在哈希表中的索引位置。關系
1、不會創(chuàng)建“類對應的散列表”
import?java.util.*;
import?java.lang.Comparable;
/**
?*?@desc 比較equals()?返回true 以及?返回false時, hashCode()的值。
?*
?*/
public?class?NormalHashCodeTest{
????public?static?void?main(String[]?args)?{
????????//?新建2個相同內(nèi)容的Person對象,
????????//?再用equals比較它們是否相等
????????Person?p1?=?new?Person("eee",?100);
????????Person?p2?=?new?Person("eee",?100);
????????Person?p3?=?new?Person("aaa",?200);
????????System.out.printf("p1.equals(p2)?:?%s;?p1(%d)?p2(%d)\n",?p1.equals(p2),?p1.hashCode(),?p2.hashCode());
????????System.out.printf("p1.equals(p3)?:?%s;?p1(%d)?p3(%d)\n",?p1.equals(p3),?p1.hashCode(),?p3.hashCode());
????}
????/**
?????*?@desc Person類。
?????*/
????private?static?class?Person?{
????????int?age;
????????String?name;
????????public?Person(String?name,?int?age)?{
????????????this.name?=?name;
????????????this.age?=?age;
????????}
????????public?String?toString()?{
????????????return?name?+?"?-?"?+age;
????????}
????????/**?
?????????*?@desc?覆蓋equals方法?
?????????*/??
????????public?boolean?equals(Object?obj){??
????????????if(obj?==?null){??
????????????????return?false;??
????????????}??
????????????//如果是同一個對象返回true,反之返回false??
????????????if(this?==?obj){??
????????????????return?true;??
????????????}??
????????????//判斷是否類型相同??
????????????if(this.getClass()?!=?obj.getClass()){??
????????????????return?false;??
????????????}??
????????????Person?person?=?(Person)obj;??
????????????return?name.equals(person.name)?&&?age==person.age;??
????????}?
????}
}
p1.equals(p2)?:?true;?p1(1169863946)?p2(1901116749)
p1.equals(p3)?:?false;?p1(1169863946)?p3(2131949076)
2、會創(chuàng)建“類對應的散列表”
如果兩個對象相等,那么它們的hashCode()值一定相同。這里的相等是指,通過equals()比較兩個對象時返回true。
如果兩個對象hashCode()相等,它們并不一定相等。因為在散列表中,hashCode()相等,即兩個鍵值對的哈希值相等。然而哈希值相等,并不一定能得出鍵值對相等。補充說一句:“兩個不同的鍵值對,哈希值相等”,這就是哈希沖突。
import?java.util.*;
import?java.lang.Comparable;
/**
?*?@desc 比較equals()?返回true 以及?返回false時, hashCode()的值。
?*
?*/
public?class?ConflictHashCodeTest1{
????public?static?void?main(String[]?args)?{
????????//?新建Person對象,
????????Person?p1?=?new?Person("eee",?100);
????????Person?p2?=?new?Person("eee",?100);
????????Person?p3?=?new?Person("aaa",?200);
????????//?新建HashSet對象?
????????HashSet?set?=?new?HashSet();
????????set.add(p1);
????????set.add(p2);
????????set.add(p3);
????????//?比較p1?和?p2,?并打印它們的hashCode()
????????System.out.printf("p1.equals(p2)?:?%s;?p1(%d)?p2(%d)\n",?p1.equals(p2),?p1.hashCode(),?p2.hashCode());
????????//?打印set
????????System.out.printf("set:%s\n",?set);
????}
????/**
?????*?@desc Person類。
?????*/
????private?static?class?Person?{
????????int?age;
????????String?name;
????????public?Person(String?name,?int?age)?{
????????????this.name?=?name;
????????????this.age?=?age;
????????}
????????public?String?toString()?{
????????????return?"("+name?+?",?"?+age+")";
????????}
????????/**?
?????????*?@desc?覆蓋equals方法?
?????????*/??
????????@Override
????????public?boolean?equals(Object?obj){??
????????????if(obj?==?null){??
????????????????return?false;??
????????????}??
????????????//如果是同一個對象返回true,反之返回false??
????????????if(this?==?obj){??
????????????????return?true;??
????????????}??
????????????//判斷是否類型相同??
????????????if(this.getClass()?!=?obj.getClass()){??
????????????????return?false;??
????????????}??
????????????Person?person?=?(Person)obj;??
????????????return?name.equals(person.name)?&&?age==person.age;??
????????}?
????}
}
p1.equals(p2)?:?true;?p1(1169863946)?p2(1690552137)
set:[(eee,?100),?(eee,?100),?(aaa,?200)]
import?java.util.*;
import?java.lang.Comparable;
/**
?*?@desc 比較equals()?返回true 以及?返回false時, hashCode()的值。
?*
?*/
public?class?ConflictHashCodeTest2{
????public?static?void?main(String[]?args)?{
????????//?新建Person對象,
????????Person?p1?=?new?Person("eee",?100);
????????Person?p2?=?new?Person("eee",?100);
????????Person?p3?=?new?Person("aaa",?200);
????????Person?p4?=?new?Person("EEE",?100);
????????//?新建HashSet對象?
????????HashSet?set?=?new?HashSet();
????????set.add(p1);
????????set.add(p2);
????????set.add(p3);
????????//?比較p1?和?p2,?并打印它們的hashCode()
????????System.out.printf("p1.equals(p2)?:?%s;?p1(%d)?p2(%d)\n",?p1.equals(p2),?p1.hashCode(),?p2.hashCode());
????????//?比較p1?和?p4,?并打印它們的hashCode()
????????System.out.printf("p1.equals(p4)?:?%s;?p1(%d)?p4(%d)\n",?p1.equals(p4),?p1.hashCode(),?p4.hashCode());
????????//?打印set
????????System.out.printf("set:%s\n",?set);
????}
????/**
?????*?@desc Person類。
?????*/
????private?static?class?Person?{
????????int?age;
????????String?name;
????????public?Person(String?name,?int?age)?{
????????????this.name?=?name;
????????????this.age?=?age;
????????}
????????public?String?toString()?{
????????????return?name?+?"?-?"?+age;
????????}
????????/**?
?????????*?@desc重寫hashCode?
?????????*/??
????????@Override
????????public?int?hashCode(){??
????????????int?nameHash?=??name.toUpperCase().hashCode();
????????????return?nameHash?^?age;
????????}
????????/**?
?????????*?@desc?覆蓋equals方法?
?????????*/??
????????@Override
????????public?boolean?equals(Object?obj){??
????????????if(obj?==?null){??
????????????????return?false;??
????????????}??
????????????//如果是同一個對象返回true,反之返回false??
????????????if(this?==?obj){??
????????????????return?true;??
????????????}??
????????????//判斷是否類型相同??
????????????if(this.getClass()?!=?obj.getClass()){??
????????????????return?false;??
????????????}??
????????????Person?person?=?(Person)obj;??
????????????return?name.equals(person.name)?&&?age==person.age;??
????????}?
????}
}
p1.equals(p2)?:?true;?p1(68545)?p2(68545)
p1.equals(p4)?:?false;?p1(68545)?p4(68545)
set:[aaa?-?200,?eee?-?100]
原則
如果一個key對象在put的時候調(diào)用hashCode()決定了存放的位置,而在get的時候調(diào)用hashCode()得到了不一樣的返回值,這個值映射到了一個和原來不一樣的地方,那么肯定就找不到原來那個鍵值對了。
推薦閱讀:
畢設有著落了!一套開源的,基于SpringBoot的車牌識別系統(tǒng)
微信掃描二維碼,關注我的公眾號
朕已閱?
評論
圖片
表情

