hashCode 是什么
下面是hashcode官方文檔的定義[摘自JavaSE6]:
- 在應(yīng)用程序的執(zhí)行期間,只要對象的equals方法的比較操作所用到的信息沒有被修改,那么對這同一個對象調(diào)用多次,hashCode方法都必須始終如一地返回同一個整數(shù)悠反。在同一個應(yīng)用程序的多次執(zhí)行過程中,每次執(zhí)行所返回的整數(shù)可以不一致。
- 如果兩個對象根據(jù)equal(Object)方法比較是相等的撇吞,那么調(diào)用這兩個對象中任意一個對象的hashCode方法都必須返回同樣的整數(shù)結(jié)果。
- 如果兩個對象根據(jù)equals(Object)方法比較是不相等的礁叔,那么調(diào)用這兩個對象中任意一個對象的hashCode方法牍颈,則不一定要產(chǎn)生不同的整數(shù)結(jié)果。但是程序員應(yīng)該知道琅关,給不相等的對象產(chǎn)生截然不同的整數(shù)結(jié)果煮岁,有可能提高散列表的性能讥蔽。
hashCode能做什么
再歸納一下就是hashCode是用于查詢使用的,而equals是用于比較兩個對象是否相等的画机。以下這段話是從別的帖子回復(fù)拷貝過來的:
hashcode是用來查找的冶伞,如果你學(xué)過數(shù)據(jù)結(jié)構(gòu)就應(yīng)該知道,在查找和排序這一章有
例如內(nèi)存中有這樣的位
0 1 2 3 4 5 6 7
而我有個類步氏,這個類有個字段叫ID,我要把這個類存放在以上8個位置之一响禽,如果不用hashcode而任意存放,那么當(dāng)查找時就需要到這八個位置里挨個去找荚醒,或者用二分法一類的算法芋类。
但如果用hashcode那就會使效率提高很多。
我們這個類中有個字段叫ID,那么我們就定義我們的hashcode為ID%8界阁,然后把我們的類存放在取得得余數(shù)那個位置侯繁。比如我們的ID為9,9除8的余數(shù)為1泡躯,那么我們就把該類存在1這個位置贮竟,如果ID是13,求得的余數(shù)是5较剃,那么我們就把該類放在5這個位置隘谣。這樣叨叙,以后在查找該類時就可以通過ID除 8求余數(shù)直接找到存放的位置了增热。但是如果兩個類有相同的hashcode怎么辦那(我們假設(shè)上面的類的ID不是唯一的)障贸,例如9除以8和17除以8的余數(shù)都是1,那么這是不是合法的确垫,回答是:可以這樣弓颈。那么如何判斷呢?在這個時候就需要定義 equals了删掀。
也就是說翔冀,我們先通過 hashcode來判斷兩個類是否存放某個桶里,但這個桶里可能有很多類披泪,那么我們就需要再通過 equals 來在這個桶里找到我們要的類纤子。
那么,重寫了equals()款票,為什么還要重寫hashCode()呢控硼?
想想,你要在一個桶里找東西艾少,你必須先要找到這個桶啊卡乾,你不通過重寫hashcode()來找到桶,光重寫equals()有什么用啊
最后缚够,我們來看一個具體的示例:
public class TestHashcode {
private int i;
public int getI(){
return i;
}
public void setI(int i){
this.i = i;
}
@Override
public int hashCode(){
return i % 10;
}
public static void main(String[] args) {
TestHashcode a = new TestHashcode();
TestHashcode b = new TestHashcode();
Set<TestHashcode> codeSet = new HashSet<TestHashcode>();
a.setI(1);
b.setI(1);
codeSet.add(a);
codeSet.add(b);
System.out.println(a == b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(codeSet);
}
}
這個輸出的結(jié)果:
false
true
false
[TestHashcode@1, TestHashcode@1]
以上這個示例幔妨,我們只是重寫了hashCode方法鹦赎,從上面的結(jié)果可以看出,雖然這兩個對象的hashCode相等误堡,但是實際上兩個對象并不是想等古话,我們沒有重寫equals方法,那么就會調(diào)用object默認(rèn)的equals方法锁施,是比較兩個對象的引用是不是相同陪踩,顯示這是兩個不同的對象,兩個對象的應(yīng)用肯定是不會相等的沾谜。這里我們將生成的兩個對象放到了HashSet中膊毁,而HashSet中只能夠存放唯一的對象胀莹,也就是相同的(適用于equals方法)的對象只會存放一個基跑,但是這里實際上是兩個對象a,b都被放到了HashSet中描焰,這就HashSet就失去了它本身的意義了媳否。
現(xiàn)在我們把equals方法給加上:
public class TestHashcode {
private int i;
public int getI(){
return i;
}
public void setI(int i){
this.i = i;
}
@Override
public boolean equals(Object o){
if(o == null){
return false;
}
TestHashcode thc = (TestHashcode)o;
if(this.i == thc.i){
return true;
}
return false;
}
@Override
public int hashCode(){
return i % 10;
}
public static void main(String[] args) {
TestHashcode a = new TestHashcode();
TestHashcode b = new TestHashcode();
Set<TestHashcode> codeSet = new HashSet<TestHashcode>();
a.setI(1);
b.setI(1);
codeSet.add(a);
codeSet.add(b);
System.out.println(a == b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(codeSet);
}
}
而此時得到的結(jié)果如下:
false
true
true
[TestHashcode@1]
從結(jié)果我們就可以看出,現(xiàn)在兩個對象完全相等了荆秦,HashSet中也只存放了一份對象篱竭。