爲何重寫equals方法必定要重寫hashcode方法

爲何重寫equals方法必定要重寫hashcode方法

  • equals() 定義在JDK的Object.java中。經過判斷兩個對象的地址是否相等(即,是不是同一個對象)來區分它們是否相等
  • hashCode()的做用是獲取散列碼
  • 若是不使用HashTable,」hashCode() 和 equals() 」沒有關係的!

HashSet、hashcoede()、equals()之間的關係java

  • 用到散列表時,」hashCode() 和 equals() 」是有關係的!ide

    例如:Hashset的插入的判斷順序是:先判斷hashcode,不相同則插入;相同則繼續比較equals是否爲true,若是爲true則表示兩個對象相等,不能插入;若是是false則會散列到其餘位置。this

  1. 兩個對象相等,equals爲true
  2. 兩個對象相等,hashcode必定相同(根據屬性計算而來,相等的對象屬性必定相等)
  3. equals爲true、hashcode必定相同
  4. 相同的hashcode,對象不必定相等(equals不必定爲true)

總結:code

  • equals=true =》hashcode()相同 、反之不行對象

  • 若是要使用散列表而且重寫了equals方法就必定要重寫hashcode()方法,以保證相同的對象不能同時加入HashSet中。get

爲何重寫equals方法必定要重寫hashcode方法?hash

先看String類重寫的這兩個方法class

public boolean equals(Object anObject) {
		//判斷地址是否同樣、同樣則直接返回
        if (this == anObject) {
            return true;
        }
        //判斷對象是否屬於String類
        if (anObject instanceof String) {
        	//開始比較
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }


public int hashCode() {
		//進行hash計算
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

如今來看本身寫的類(要求 id和name 相同則視爲同一個對象)
一、先看自動生成的者兩個方法
默認生成的比較了book類的全部參數,以及進行了哈希運算。方法

class Book1 {
    int id;
    String name;
    String author;
    double price;
 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book1 book1 = (Book1) o;
        return id == book1.id &&
                Double.compare(book1.price, price) == 0 &&
                Objects.equals(name, book1.name) &&
                Objects.equals(author, book1.author);
    }

    @Override
    public int hashCode() {

        return Objects.hash(id, name, author, price);
    }
}

二、要求是di和name相同則視爲同一本書、即同一對象,相同的對象不能加入到散列表中,只須要比較id和name,改寫以下總結

/**
     * 重寫equals方法比較id和name
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Book1 book1 = (Book1) o;
        return id == book1.id && Objects.equals(name, book1.name);
    }

    /**
     * 重寫equals要重寫hashcode  set加入時會先判斷hashcode是否相等,再判斷是否equals
     * 只有hashcode相同 和equals 同時成立  才能保證set的全部元素都不相等
     * @return
     */
    @Override
    public int hashCode() {

        return Objects.hash(id, name);
    }

若是隻是改寫了equals方法 hashcode方法默認仍是進行四個參數的哈希運算,計算出的兩個對象的若是id和name相同,author或者price不一樣也會計算出不一樣的hashcode。這樣的話咱們自定義的兩個相同的對象都能成功加入hashset,違背原則,因此必須同時覆蓋這兩個方法。

Book1 b1 = new Book1(1, "hh", "zs", 122.0);
 Book1 b2 = new Book1(1, "hh", "zh", 112.0);

這兩個對象只能加進去一個到HashSet中

相關文章
相關標籤/搜索