1. 程式人生 > >判斷兩個物件是否相等,hashcode和equals方法的聯絡

判斷兩個物件是否相等,hashcode和equals方法的聯絡

1、在集合中考慮兩個物件是否相同的規則是:

第一步:如果hashCode()相等,則進行第二步,否則不相同。

第二步:檢視equals()相等就相等,否則不相同

2、hashcode是物件或者變數通過雜湊演算法計算出來的hash值,不同物件是不一樣的,同一個物件是不變的。

3、equals()相等,hashcode一定相等

hashcode不相等,equals一定不相同

4、在重寫類的equals()方法時都會重寫hashcode()方法。

如果重寫了equals(),但是沒有重寫hashcode()則會造成如下問題

public class ObjectClass {
    public static void 
main(String[] args) { Set<Demo1> demo1Set=new HashSet<>(); Demo1 demo1=new Demo1(1,2); Demo1 demo2=new Demo1(3,4); Demo1 demo3=new Demo1(5,6); demo1Set.add(demo1); demo1Set.add(demo2); demo1Set.add(demo3); System.out.println(demo1Set);
Demo1 demo4=new Demo1(1,2); demo1Set.add(demo4); System.out.println(demo1Set); System.out.println(demo1.hashCode()); System.out.println(demo4.hashCode()); System.out.println(demo1.hashCode()); } } class Demo1{ private int value; private int
id; public Demo1(int value,int id){ this.value=value; this.id=id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Demo1 demo1 = (Demo1) o; if (id != demo1.id) return false; if (value != demo1.value) return false; return true; } // @Override // public int hashCode() { // int result = value; // result = 31 * result + id; // return result; // } @Override public String toString() { return "Demo1{" + "value=" + value + ", id=" + id + '}'; } }
會造成set中有重複的資料

[Demo1{value=3, id=4}, Demo1{value=1, id=2}, Demo1{value=5, id=6}]
[Demo1{value=3, id=4}, Demo1{value=1, id=2}, Demo1{value=1, id=2},Demo1{value=5, id=6}]
2133927002
1173230247
2133927002

也就是說,在這種情況下,不重新寫hashcode方法,兩個物件是的hashcode值Object方法裡面是不一樣的。所以set集合裡面就會認為是兩個不同的物件,所以會都有。所以重寫了equals方法必須重寫hashcode方法。

例項應用:

public static boolean isAllSelected(WipPackage wipPackage, WiseNewsSession wiseNewsSession) {
    ConfigManager configManager = wiseNewsSession.getConfigManager();
WipPackage wipPackageFrom4VS=getWipPackage4VS(wiseNewsSession, configManager);
return wipPackageFrom4VS.equals(wipPackage);
}

比較wipPackageFrom4VS和wipPackage兩個物件是否相等。顯然如果不重寫WipPackage的hashCode()方法

這兩個物件的hashCode值是不相等的(因為是不同的物件)。那麼既然兩個物件的hashcode值不相等,

即使兩個物件對應欄位的值相等,equals()方法也一定是false。

so

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
}
    if (o == null || getClass() != o.getClass()) {
        return false;
}

    WipPackage that = (WipPackage) o;
if (wisesearch != that.wisesearch) {
        return false;
}
    if (wisesearchpro != that.wisesearchpro) {
        return false;
}
    if (video != that.video) {
        return false;
}
    if (cartoon != that.cartoon) {
        return false;
}
    if (web != that.web) {
        return false;
}
    if (ad != that.ad) {
        return false;
}
    return wiselive == that.wiselive;
}

@Override
public int hashCode() {
    int result = (wisesearch ? 1 : 0);
result = 31 * result + (wisesearchpro ? 1 : 0);
result = 31 * result + (video ? 1 : 0);
result = 31 * result + (cartoon ? 1 : 0);
result = 31 * result + (web ? 1 : 0);
result = 31 * result + (ad ? 1 : 0);
result = 31 * result + (wiselive ? 1 : 0);
return result;
}

那麼另一個問題來了,怎麼重寫hashCode()方法和equals()方法呢?

一定要確保兩個物件的欄位相同,hashCode()和equals()就相同。

那麼為什麼要乘以31呢?

The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.