天天看點

hashCode與equals的差別與聯系

一、equals方法的作用

   1、預設情況(沒有覆寫equals方法)下equals方法都是調用object類的equals方法,而object的equals方法主要用于判斷對象的記憶體位址引用是不是同一個位址(是不是同一個對象)。

2 、要是類中覆寫了equals方法,那麼就要根據具體的代碼來确定equals方法的作用了,覆寫後一般都是通過對象的内容是否相等來判斷對象是否相等。

沒有覆寫equals方法代碼如下:

[java] view plaincopyprint?

//學生類  

public class student {  

    private int age;  

    private string name;  

    public student() {  

    }  

    public student(int age, string name) {  

        super();  

        this.age = age;  

        this.name = name;  

    public int getage() {  

        return age;  

    public string getname() {  

        return name;  

    public void setage(int age) {  

    public void setname(string name) {  

}  

java代碼  

hashCode與equals的差別與聯系

測試 代碼如下:

import java.util.hashset;  

import java.util.linkedlist;  

import java.util.set;  

public class equalstest {  

    public static void main(string[] args) {  

        linkedlist<student> list = new linkedlist<student>();  

        set<student> set = new hashset<student>();  

        student stu1  = new student(3,"張三");  

        student stu2  = new student(3,"張三");  

        system.out.println("stu1 == stu2 : "+(stu1 == stu2));  

        system.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));  

        list.add(stu1);  

        list.add(stu2);  

        system.out.println("list size:"+ list.size());  

        set.add(stu1);  

        set.add(stu2);  

        system.out.println("set size:"+ set.size());  

hashCode與equals的差別與聯系

運作結果:

stu1 == stu2 : false

stu1.equals(stu2) : false

list size:2

set size:2

結果分析:student類沒有覆寫equals方法,stu1調用equals方法實際上調用的是object的equals方法。是以采用對象記憶體位址是否相等來判斷對象是否相等。因為是兩個新對象是以對象的記憶體位址不相等,是以stu1.equals(stu2) 是false。

3、我們覆寫一下equals方法(age和name屬性),讓student類其通過判斷對象的内容是否相等來确定對象是否相等。

覆寫後的student類:

    @override  

    public boolean equals(object obj) {  

        if (this == obj)  

            return true;  

        if (obj == null)  

            return false;  

        if (getclass() != obj.getclass())  

        student other = (student) obj;  

        if (age != other.age)  

        if (name == null) {  

            if (other.name != null)  

                return false;  

        } else if (!name.equals(other.name))  

        return true;  

hashCode與equals的差別與聯系

stu1.equals(stu2) : true

結果分析:因為student兩個對象的age和name屬性相等,而且又是通過覆寫equals方法來判斷的,所示stu1.equals(stu2) 為true。注意以上幾次測試list和set的size都是2

二、hashcode

4、通過以上的代碼運作,我們知道equals方法已經生效。接下來我們在覆寫一下hashcode方法(通過age和name屬性來生成hashcode)并不覆寫equals方法,其中hash碼是通過age和name生成的。

覆寫hashcode後的student類:

    public int hashcode() {  

        final int prime = 31;  

        int result = 1;  

        result = prime * result + age;  

        result = prime * result + ((name == null) ? 0 : name.hashcode());  

        return result;  

    }     

hashCode與equals的差別與聯系

hashcode :775943

結果分析:我們并沒有覆寫equals方法隻覆寫了hashcode方法,兩個對象雖然hashcode一樣,但在将stu1和stu2放入set集合時由于equals方法比較的兩個對象是false,是以就沒有在比較兩個對象的hashcode值。

5、我們覆寫一下equals方法和hashcode方法。

student代碼如下:

        system.out.println("hashcode : "+ result);  

hashCode與equals的差別與聯系

stu1.equals(stu2) :true

set size:1

結果分析:stu1和stu2通過equals方法比較相等,而且傳回的hashcode值一樣,是以放入set集合中時隻放入了一個對象。

6、下面我們讓兩個對象equals方法比較相等,但hashcode值不相等試試。

student類的代碼如下:

    <span style="color: rgb(255, 0, 0);">private static int index=5;</span>  

        result = prime * result + <span style="color: rgb(255, 0, 0);">(age+index++)</span>;  

        <span style="color: rgb(255, 0, 0);">system.out.println("result :"+result);</span>  

hashCode與equals的差別與聯系

    <span style="color: #ff0000;">private static int index=5;</span>  

        result = prime * result + <span style="color: #ff0000;">(age+index++)</span>;  

        <span style="color: #ff0000;">system.out.println("result :"+result);</span>  

hashcode :776098

hashcode :776129

結果分析:雖然stu1和stu2通過equals方法比較相等,但兩個對象的hashcode的值并不相等,是以在将stu1和stu2放入set集合中時認為是兩個不同的對象。

7、修改stu1的某個屬性值

hashCode與equals的差別與聯系

測試代碼如下:

        stu1.setage(34);  

        system.out.println("remove stu1 : "+set.remove(stu1));  

hashCode與equals的差別與聯系

stu1.equals(stu2) : true

hashcode : 775943

hashcode : 775943

hashcode : 776904

remove stu1 : false

結果分析:

當我們将某個對象存到set中時,如果該對象的屬性參與了hashcode的計算,那麼以後就不能修改該對象參與hashcode計算的那些屬性了,否則會引起意向不到的錯誤的。正如測試中,不能夠移除stu1對象。

總結:

1、equals方法用于比較對象的内容是否相等(覆寫以後)

2、hashcode方法隻有在集合中用到

3、當覆寫了equals方法時,比較對象是否相等将通過覆寫後的equals方法進行比較(判斷對象的内容是否相等)。

4、将對象放入到集合中時,首先判斷要放入對象的hashcode值與集合中的任意一個元素的hashcode值是否相等,如果不相等直接将該對象放入集合中。如果hashcode值相等,然後再通過equals方法判斷要放入對象與集合中的任意一個對象是否相等,如果equals判斷不相等,直接将該元素放入到集合中,否則不放入。

5、将元素放入集合的流程圖:

hashCode與equals的差別與聯系
hashCode與equals的差別與聯系
hashCode與equals的差別與聯系

6、hashset中add方法源代碼:

public boolean add(e e) {  

    return map.put(e, present)==null;  

hashCode與equals的差別與聯系

map.put源代碼:

<pre class="java" name="code"> public v put(k key, v value) {  

        if (key == null)  

            return putfornullkey(value);  

        int hash = hash(key.hashcode());  

        int i = indexfor(hash, table.length);  

        for (entry<k,v> e = table[i]; e != null; e = e.next) {  

            object k;  

            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  

                v oldvalue = e.value;  

                e.value = value;  

                e.recordaccess(this);  

                return oldvalue;  

            }  

        }  

        modcount++;  

        addentry(hash, key, value, i);  

        return null;  

    }</pre>  

<pre></pre>  

<pre></pre>  

特别說明:尊重作者的勞動成果,轉載請注明出處哦~~~http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt277