有關java中的hashCode問題

來源:互聯網
上載者:User

標籤:定義類   java   需要   ash   不重複   關於   尋找   add   輸入   

1. HashSet集合儲存資料的結構(雜湊表)1.1 什麼是雜湊表?

雜湊表底層使用的也是數組機制,數組中也存放對象,而這些對象往數組中存放時的位置比較特殊,當需要把這些對象給數組中存放時,那麼會根據這些對象的特有資料結合相應的演算法,計算出這個對象在數組中的位置,然後把這個對象存放在數組中。而這樣的數組就稱為雜湊數組,即就是雜湊表。

1.2 雜湊表儲存資料結構原理

當向雜湊表中存放元素時,需要根據元素的特有資料結合相應的演算法,這個演算法其實就是Object類中的hashCode方法。由於任何對象都是Object類的子類,所以任何對象也擁有這個方法。即就是在給雜湊表中存放對象時,會調用對象的hashCode方法,算出對象在表中的存放位置,這裡需要注意,如果兩個對象hashCode方法算出結果一樣,這樣現象稱為雜湊衝突,這時會調用對象的equals方法,比較這兩個對象是不是同一個對象,如果equals方法返回的是true,那麼就不會把第二個對象存放在雜湊表中,如果返回的是false,就會把這個值存放在雜湊表中。

1.3 雜湊表儲存資料結構原理圖

2. hash

hash是散列的意思,就是把任意長度的輸入,通過散列演算法變換成固定長度的輸出,該輸出就是散列值。關於散列值,有以下幾個關鍵結論:

  1. 如果散列表中存在和散列原始輸入K相等的記錄,那麼K必定在f(K)的儲存位置上

  2. 不同關鍵字經過散列演算法變換後可能得到同一個散列地址,這種現象稱為碰撞

  3. 如果兩個hash值不同(前提是同一hash演算法),那麼這兩個hash值對應的原始輸入必定不同

3. hashCode
  1. hashCode的存在主要是為了尋找的快捷性,hashCode是用來在散列儲存結構中確定對象的儲存地址的

  2. 如果兩個對象equals相等,那麼這兩個對象的hashCode一定也相同

  3. 如果對象的equals方法被重寫,那麼對象的hashCode方法也盡量重寫

  4. 如果兩個對象的hashCode相同,不代表兩個對象就相同,只能說明這兩個對象在散列儲存結構中,存放於同一個位置

  5. 如果根據equals方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不一定產生不同的整數結果。但是,程式員應該意識到,為不相等的對象產生不同整數結果可以提高雜湊表的效能。

4. hashCode作用

我們知道Set裡面的元素是不可以重複的,那麼如何做到?

Set是根據equals()方法來判斷兩個元素是否相等的。比方說Set裡面已經有1000個元素了,那麼第1001個元素進來的時候,最多可能調用1000次equals方法,如果equals方法寫得複雜,對比的東西特別多,那麼效率會大大降低。使用HashCode就不一樣了,比方說HashSet,底層是基於HashMap實現的,先通過HashCode取一個模,這樣一下子就固定到某個位置了,如果這個位置上沒有元素,那麼就可以肯定HashSet中必定沒有和新添加的元素equals的元素,就可以直接存放了,都不需要比較;如果這個位置上有元素了,逐一比較,比較的時候先比較HashCode,HashCode都不同接下去都不用比了,肯定不一樣,HashCode相等,再equals比較,沒有相同的元素就存,有相同的元素就不存。如果原來的Set裡面有相同的元素,只要HashCode的產生方式定義得好(不重複),不管Set裡面原來有多少元素,只需要執行一次的equals就可以了。這樣一來,實際調用equals方法的次數大大降低,提高了效率。

5. HashSet儲存JavaAPI中的類型元素

給HashSet中儲存JavaAPI中提供的類型元素時,不需要重寫元素的hashCode和equals方法,因為這兩個方法,在JavaAPI的每個類中已經重寫完畢,如String類、Integer類等。

舉個栗子:

public class HashSetDemo {    public static void main(String[] args) {        //建立HashSet對象        HashSet<String> hs = new HashSet<String>();        //給集合中添加自訂對象        hs.add("zhangsan");        hs.add("lisi");        hs.add("wangwu");        hs.add("zhangsan");        //取出集合中的每個元素        Iterator<String> it = hs.iterator();        while(it.hasNext()){            String s = it.next();            System.out.println(s);        }    }}

輸出結果:

wangwu
lisi
zhangsan

6. HashSet儲存自訂類型元素

給HashSet中存放自訂類型元素時,需要重寫對象中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的對象唯一

舉個栗子:

自訂Student類

public class Student {    private String name;    private int age;    public Student(String name, int age) {        super();        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString() {        return "Student [name=" + name + ", age=" + age + "]";    }    @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + age;        result = prime * result + ((name == null) ? 0 : name.hashCode());        return result;    }    @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if(!(obj instanceof Student)){            System.out.println("類型錯誤");            return false;        }        Student other = (Student) obj;        return this.age ==  other.age && this.name.equals(other.name);    }}

建立HashSet集合,儲存Student對象

public class HashSetDemo {    public static void main(String[] args) {        //建立HashSet對象        HashSet<Student> hs = new<Student> HashSet();        //給集合中添加自訂對象        hs.add(new Student("zhangsan",21));        hs.add(new Student("lisi",22));        hs.add(new Student("wangwu",23));        hs.add(new Student("zhangsan",21));        //取出集合中的每個元素        Iterator it = hs.iterator();        while(it.hasNext()){            Student s = (Student)it.next();            System.out.println(s);        }    }}

輸出結果:

Student [name=lisi, age=22]
Student [name=zhangsan, age=21]
Student [name=wangwu, age=23]

7. 寫在後面

保證HashSet集合元素的唯一,其實就是根據對象的hashCode和equals方法來決定的。如果我們往集合中存放自訂的對象,那麼保證其唯一,就必須重寫hashCode和equals方法建立屬於當前對象的比較方式。

有關java中的hashCode問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.