我想寫的問題有三個:
1、首先我們為什麼需要重寫hashCode()方法和equals()方法
2、在什麼情況下需要重寫hashCode()方法和equals()方法
3、如何重寫這兩個方法
*********************************************************************
第一個問題:為什麼需要重寫hashCode()方法和equals()方法
中的超類Object類中定義的equals()方法是用來比較兩個引用所指向的對象的記憶體位址是否一緻
Object類中equals()方法的源碼
public boolean equals(Object obj) {
return (this == obj);
}
********************************************************************
Object類中的hashCode()方法,用native關鍵字修飾,說明這個方法是個原生函數,也就說這個方法的實作不是用java語言實作的,是使用c/c++實作的,并且被編譯成了DLL,由java去調用,jdk源碼中不包含。對于不同的平台它們是不同的,java在不同的中調用不同的native方法實作對作業系統的通路,因為java語言不能直接通路作業系統底層,因為它沒有指針。
這種方法調用的過程:
1、在java中申明native方法,然後編譯
2、用javah産生一個 .h 檔案
3、寫一個 .cpp檔案實作native導出方法,其中需要包含第二步産生的.h檔案(其中又包含了jdk帶的jni.h檔案);
4、将.cpp檔案編譯成動态連結庫檔案
5、在java中用System.loadLibrary()檔案加載第四步産生的動态連結庫檔案,然後這個navite方法就可被通路了
Java的API文檔對hashCode()方法做了詳細的說明,這也是我們重寫hashCode()方法時的原則【Object類】
重點要注意的是:
a. 在java應用程式運作時,無論何時多次調用同一個對象時的hsahCode()方法,這個對象的hashCode()方法的傳回值必須是相同的一個int值
b. 如果兩個對象equals()傳回值為true,則他們的hashCode()也必須傳回相同的int值
c. 如果兩個對象equals()傳回值為false,則他們的hashCode()傳回值也必須不同
public native int hashCode();
現在到了說正題了,為什麼要重寫
我們在定義類時,我們經常會希望兩個不同對象的某些屬性值相同時就認為他們相同,是以我們要重寫equals()方法,按照原則,我們重寫了equals()方法,也要重寫hashCode()方法,要保證上面所述的b,c原則;是以java中的很多類都重寫了這兩個方法,例如String類,包裝類
4、第二個問題:在什麼情況下需要重寫hashCode()方法和equals()方法
當我們自定義的一個類,想要把它的執行個體儲存在集合中時,我們就需要重寫這兩個方法;集合(Collection)有兩個類,一個是List,一個是Set
List:集合中的元素是有序的,可以重複的
Set:無序,不可重複的
以HashSet來說明:
HashSet存放元素時,根據元素的hashCode值快速找到要存儲的位置,如果這個位置有元素,兩個對象通過equals()比較,如果傳回值為true,則不放入;如果傳回值為false,則這個時候會以連結清單的形式在同一個位置上存放兩個元素,這會使得HashSet的性能降低,因為不能快速定位了。還有一種情況就是兩個對象的hashCode()傳回值不同,但是equals()傳回true,這個時候HashSet會把這兩個對象都存進去,這就和Set集合不重複的規則相悖了;是以,我們重寫了equals()方法時,要按照b,c規則重寫hashCode()方法!
5、第三個問題:如何重寫這兩個方法
我寫了一個例子,大家可以看一下
*******************************************************************************
package cn.hashCode.jing;
/**
*定義一個Ponint類,用來測試Set集合儲存元素的方式中
*hashCode()方法和equals()方法對Set集合儲存元素影響
*
*/
public final class Point {
private int x;
private int y;
public Point(){
super();
}
public Point(int x,int y){
this.x=x;
this.y=y;
public int getX() {
return x;
public void setX(int x) {
this.x = x;
public int getY() {
return y;
public void setY(int y) {
this.y = y;
@Override
public boolean equals(Object obj){
if(this==obj){
return true;
}
if(obj!=null && obj.getClass()==Point.class){
Pointpo=(Point)obj;
if(this.x==po.x && this.y==po.y){
return true;
}
return false;
public int hashCode(){
return 7*x+31*y;
/*以下是自動生成的
@Override
publicboolean equals(Object obj) {
if(this == obj)
returntrue;
if(obj == null)
returnfalse;
if(getClass() != obj.getClass())
Pointother = (Point) obj;
if(x != other.x)
if(y != other.y)
returntrue;
publicint hashCode() {
finalint prime = 31;
intresult = 1;
result= prime * result + x;
result= prime * result + y;
returnresult;
}*/
public String toString(){
return x+","+y+" ";
import java.util.HashSet;
public class TestHashSet {
public static void main(String[] args) {
HashSet<Point>hs=new HashSet<Point>();
Pointp1=new Point(3,4);
Pointp2=new Point(6,4);
Pointp3=new Point(10,7);
Pointp4=new Point(8,9);
Pointp5=new Point(3,4);
hs.add(p1);
hs.add(p2);
hs.add(p3);
hs.add(p4);
hs.add(p5);
System.out.println(p1.equals(p5));
System.out.println(p1.hashCode());
System.out.println(p5.hashCode());
System.out.println(hs);