1. 程式人生 > >關於為什麼要重寫hashCode()方法和equals()方法及如何重寫

關於為什麼要重寫hashCode()方法和equals()方法及如何重寫

我想寫的問題有三個:

1、首先我們為什麼需要重寫hashCode()方法和equals()方法

2、在什麼情況下需要重寫hashCode()方法和equals()方法

3、如何重寫這兩個方法

*********************************************************************

第一個問題:為什麼需要重寫hashCode()方法和equals()方法

    Java中的超類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;

    }

    @Override

    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())

           returnfalse;

       Pointother = (Point) obj;

       if(x != other.x)

           returnfalse;

       if(y != other.y)

           returnfalse;

       returntrue;

    }

    @Override

    publicint hashCode() {

       finalint prime = 31;

       intresult = 1;

       result= prime * result + x;

       result= prime * result + y;

       returnresult;

    }*/

    public String toString(){

       return x+","+y+" ";

    }

}

package cn.hashCode.jing;

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);

}

}

結果:true

145

145

[3,4 , 6,4 , 10,7 ,8,9 ]