1. 程式人生 > >每天學一點 面試題 1 ,HashCode與 equals。

每天學一點 面試題 1 ,HashCode與 equals。

hashcode 和 equals的區別

1.如果兩個物件的hashcode相等,那麼這兩個物件相等嗎?
不一定相等
hashcode()方法是實際上返回的就是物件儲存的實體地址(實際可能並不是)
比如:
String s1 = new String(”1“);
String s2= new String(”1“);
那麼s1.hashCode() 是等於 s2.hashCode()的。

2.如果兩個物件的equals相等,那麼這兩個物件相等嗎?
不一定相等。
如果沒有重寫equals()時候,那麼會繼承Object裡面的equals() 程式碼如下。

 public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    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;
}

不難看出,當String物件時候Object裡面的方法判斷了字元是否相等,相等就返回true;所以一般需要使用equals時候最好重寫。

   public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    }

3.這裡我們首先要明白一個問題:
equals()相等的兩個物件,hashcode()一定相等;
equals()不相等的兩個物件,卻並不能證明他們的hashcode()不相等。換句話說,equals()方法不相等的兩個物件,hashcode()有可能相等。

mport java.util.*; 
public class HashSetTest 
{ 
 public static void main(String[] args) 
  { 
             HashSet hs=new HashSet(); 
             hs.add(new Student(1,"zhangsan")); 
             hs.add(new Student(2,"lisi")); 
             hs.add(new Student(3,"wangwu")); 
             hs.add(new Student(1,"zhangsan")); 

             Iterator it=hs.iterator(); 
             while(it.hasNext()) 
             { 
                    System.out.println(it.next()); 
             } 
 } 
} 
class Student 
   { 
 int num; 
 String name; 
 Student(int num,String name) 
            { 
            this.num=num; 
             this.name=name; 
             } 
          public String toString() 
            { 
                return num+":"+name; 
             } 
       }      

輸出結果為:
1:zhangsan
1:zhangsan
3:wangwu
2:lisi

問題出現了,為什麼hashset添加了相等的元素呢,這是不是和hashset的原則違背了呢?回答是:沒有
因為在根據hashcode()對兩次建立的new Student(1,“zhangsan”)物件進行比較時,生成的是不同的雜湊碼值,所以hashset把他當作不同的物件對待了,當然此時的equals()方法返回的值也不等(這個不用解釋了吧)。那麼為什麼會生成不同的雜湊碼值呢?上面我們在比較s1和s2的時候不是生成了同樣的雜湊碼嗎?原因就在於我們自己寫的Student類並沒有重新自己的hashcode()和equals()方法,所以在比較時,是繼承的object類中的hashcode()方法,呵呵,各位還記得object類中的hashcode()方法比較的是什麼吧!!

它是一個本地方法,比較的是物件的地址(引用地址),使用new方法建立物件,兩次生成的當然是不同的物件了(這個大家都能理解吧。。。),造成的結果就是兩個物件的hashcode()返回的值不一樣。所以根據第一個準則,hashset會把它們當作不同的物件對待,自然也用不著第二個準則進行判定了。那麼怎麼解決這個問題呢??
答案是:在Student類中重新hashcode()和equals()方法。

public int hashCode() 
{ 
        return 	name.hashCode(); 
} 

【原則】按照equals( )中比較兩個物件是否一致的條件用到的屬性來重寫hashCode()。

{1}. 常用的辦法就是利用涉及到的的屬性進行線性組合。

{2}. 線性組合過程中涉及到的組合係數自定義即可。

注意,拼接之後的數值不能超過整形的表達範圍。

{3}. 公式:屬性1的int形式+ C1屬性2的int形式+ C2屬性3的int形式+ …