JAVA hashCode應用辦法詳解。本站提示廣大學習愛好者:(JAVA hashCode應用辦法詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是JAVA hashCode應用辦法詳解正文
一.成績引入
談到hashCode就不能不說equals辦法,兩者均在Object類裡,因為Object類是一切類的基類,所以一切類裡都可以重寫這兩個辦法。
要想較清楚的懂得,須要先曉得容器Collection,Set,list,Map(key值弗成反復),Set元素無序不反復,list元素有序可反復,那末JVM是若何肯定分歧的元素的呢?
豈非是逐一比擬麼,那樣效力就太低了,JVM采取hash的辦法(hash地址紛歧定是現實的物理地址),看看這個地址上能否有內容,沒的話就以為不存在雷同對象……
且看上面分化……
二.成績剖析
起首equals()和hashcode()這兩個辦法都是從object類中繼續過去的,equals()辦法在object類中界說以下:
public boolean equals(Object obj) {
return (this == obj);
}
從聲明看出很顯著是對兩個對象的地址值停止的比擬(即比擬援用能否雷同)。然則我們必須清晰,當String 、Math、還有Integer、Double。。。。等這些封裝類在應用equals()辦法時,曾經籠罩了object類的
equals()辦法。
2. 其次是hashcode() 辦法,在object類中界說以下:
public native int hashCode();
解釋是一個當地辦法,它的完成是依據當地機械相干的。
public int hashCode() {
int h = hash;
if (h == 0) {
nt off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
說明一下這個法式: s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] ,可以看出hash地址紛歧定是現實的內存地址。
3. 若干標准
若重寫equals(Object obj)辦法,有需要重寫hashcode()辦法,確保經由過程equals(Object obj)辦法斷定成果為true的兩個對象具有相等的hashcode()前往值。說得簡略點就是:“假如兩個對象雷同,那末他們的hashcode應當 相等”。不外請留意:這個只是標准,假如你非要寫一個類讓equals(Object obj)前往true而hashcode()前往兩個不相等的值,編譯和運轉都是不會報錯的。不外如許違背了Java標准,法式也就埋下了BUG。
假如equals(Object obj)前往false,即兩個對象“不雷同”,其實不請求對這兩個對象挪用hashcode()辦法獲得兩個不雷同的數(更印證了hash地址紛歧定是現實的內存地址)。說的簡略點就是:“假如兩個對象不雷同,他們的hashcode能夠雷同”。
依據這兩個標准,不可貴到以下推論:
1、假如兩個對象equals,Java運轉時情況會以為他們的hashcode必定相等。
2、假如兩個對象不equals,他們的hashcode有能夠相等。
3、假如兩個對象hashcode相等,他們紛歧定equals(我懂得是因為hash抵觸形成的)。
4、假如兩個對象hashcode不相等,他們必定不equals。
三.成績處理
測試hashCode和equals辦法的應用……
import java.util.HashMap;
import java.util.Map;
class A {
@Override
public boolean equals(Object obj) {
System.out.println("斷定equals");
return true;
}
@Override
public int hashCode() {
System.out.println("斷定hashcode");
return 1;
}
}
public class Test {
public static void main(String[] args) {
Map<A,Object> map = new HashMap<A, Object>();
map.put(new A(), new Object());
map.put(new A(), new Object());
System.out.println(map.size());
}
}
輸入:
斷定hashcode
斷定hashcode
斷定equals
2
針對成果剖析以下:
可以看出,JRE會挪用new A()這個對象的hashcode()辦法。個中:打印出的第一行“斷定hashcode”是第一次map.put(new A(), new Object())所打印出的。 接上去的“斷定hashcode”和“斷定equals”是第二次map.put(new A(), new Object())所打印出來的。當第一次map.put(new A(), new Object())的時刻,明顯,這時候候沒有雷同的,由於這個map中都還沒有器械,所以這時候候hashcode不相等,則沒有需要再挪用equals(Object obj)辦法了。當第二次map.put(new A(), new Object())的時刻,JRE這時候候發明了map中有兩個雷同的hashcode(由於我重寫了A類的hashcode()辦法永久都前往1),所以有需要挪用equals(Object obj)辦法停止斷定了。然後發明兩個對象不equals(由於我重寫了equals(Object obj)辦法,永久都前往false)。這時候候斷定停止,斷定成果:兩次存入的對象不是雷同的對象。所以最初打印map的長度的時刻顯示成果是:2。
四.若干注事事項
我們還應當留意,Java說話對equals()的請求以下,這些請求是必需遵守的:
對稱性:假如x.equals(y)前往是“true”,那末y.equals(x)也應當前往是“true”。
反射性:x.equals(x)必需前往是“true”。
傳遞性:假如x.equals(y)前往是“true”,並且y.equals(z)前往是“true”,那末z.equals(x)也應當前往是“true”。
分歧性:假如x.equals(y)前往是“true”,只需x和y內容一向不變,不論你反復x.equals(y)若干次,前往都是“true”。
任何情形下,x.equals(null),永久前往是“false”;x.equals(和x分歧類型的對象)永久前往false
以上這五點是重寫equals()辦法時,必需遵照的原則,假如違背會湧現意想不到的成果,請年夜家必定要遵照……