每天學一點 面試題 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形式+ …