1. 程式人生 > >(面試題)兩個物件值相同 (x.equals(y) == true) ,但卻可有不同的 hash code ,這 句話對不對

(面試題)兩個物件值相同 (x.equals(y) == true) ,但卻可有不同的 hash code ,這 句話對不對

(面試題)兩個物件值相同 (x.equals(y) == true) ,但卻可有不同的 hash code ,這 句話對不對
答:不對,有相同的 hash code
這是java語言的定義:

  1. 物件相等則hashCode一定相等;
  2. hashCode相等物件未必相等

1.如果是基本變數,沒有hashcode和equals方法,基本變數的比較方式就只有==;

2.如果是變數,由於在java中所有變數定義都是一個指向實際儲存的一個控制代碼(你可以理解為c++中的指標),在這裡==是比較控制代碼的地址(你可以理解為指標的儲存地址),而不是控制代碼指向的實際記憶體中的內容,如果要比較實際記憶體中的內容,那就要用equals方法,但是!!!

如果是你自己定義的一個類,比較自定義類用equals和是一樣的,都是比較控制代碼地址,因為自定義的類是繼承於object,而object中的equals就是用來實現的,你可以看原始碼。

那為什麼我們用的String等等型別equals是比較實際內容呢,是因為String等常用類已經重寫了object中的equals方法,讓equals來比較實際內容,你也可以看原始碼。

  1. hashcode

在一般的應用中你不需要了解hashcode的用法,但當你用到hashmap,hashset等集合類時要注意下hashcode。

你想通過一個object的key來拿hashmap的value,hashmap的工作方法是,通過你傳入的object的hashcode在記憶體中找地址,當找到這個地址後再通過equals方法來比較這個地址中的內容是否和你原來放進去的一樣,一樣就取出value。

所以這裡要匹配2部分,hashcode和equals

但假如說你new一個object作為key去拿value是永遠得不到結果的,因為每次new一個object,這個object的hashcode是永遠不同的,所以我們要重寫hashcode,你可以令你的hashcode是object中的一個恆量,這樣永遠可以通過你的object的hashcode來找到key的地址,然後你要重寫你的equals方法,使記憶體中的內容也相等。。。

一般來講,equals這個方法是給使用者呼叫的,如果你想判斷2個物件是否相等,你可以重寫equals方法,然後在程式碼中呼叫,就可以判斷他們是否相等了。簡單來講,equals方法主要是用來判斷從表面上看或者從內容上看,2個物件是不是相等。舉個例子,有個學生類,屬性只有姓名和性別,那麼我們可以認為只要姓名和性別相等,那麼就說這2個物件是相等的。

hashcode方法一般使用者不會去呼叫,比如在hashmap中,由於key是不可以重複的,他在判斷key是不是重複的時候就判斷了hashcode這個方法,而且也用到了equals方法。這裡不可以重複是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相當於是一個物件的編碼,就好像檔案中的md5,他和equals不同就在於他返回的是int型的,比較起來不直觀。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。舉個例子,還是剛剛的例子,如果姓名和性別相等就算2個物件相等的話,那麼hashcode的方法也要返回姓名的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。

要從物理上判斷2個物件是否相等,用==就可以了
分類: 面試題
好文要頂 關注我 收藏該文
嗨,你的益達~~~
關注 - 16
粉絲 - 62
+加關注
0 0
« 上一篇:有關java呼叫方法引數傳遞的分析
» 下一篇:【轉】java io 流 設計模式
posted @ 2013-08-08 16:16 嗨,你的益達~~~ 閱讀(14102) 評論(6) 編輯 收藏

評論列表
#1樓 2014-11-14 11:21 whzhaochao
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.test;

public class Main {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Test x=new Test("x");
    Test y=new Test("y");
    System.out.println("x HashCode="+x.hashCode());
    System.out.println("y HashCode="+y.hashCode());
    System.out.println(x.equals(y)==true);
}

}

class Test{
private String name;
public Test(String name){
this.name=name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
    return true;
}

}

結果
1
2
3
x HashCode=151
y HashCode=152
true
支援(0)反對(2)
#2樓 2015-09-04 11:51 樹根根
@ whzhaochao
真逗,你重寫的equal就是個圈套,比都不比,直接return true; ,你在豁樓主嗎?
支援(1)反對(2)
#3樓 2015-09-16 13:04 popezong
@ 樹根根
你這。。仔細看好了 上面那個人是對的。樓主自己理解不對
支援(0)反對(0)
#4樓 2016-10-12 10:48 LytZz
hashCode 的常規協定是:

1.在 Java 應用程式執行期間,在對同一物件多次呼叫 hashCode 方法時,必須一致地返回相同的整數,前提是將物件進行 equals 比較時所用的資訊沒有被修改。從某一應用程式的一次執行到同一應用程式的另一次執行,該整數無需保持一致。
2.如果根據 equals(Object) 方法,兩個物件是相等的,那麼對這兩個物件中的每個物件呼叫 hashCode 方法都必須生成相同的整數結果。
3.如果根據 equals(java.lang.Object) 方法,兩個物件不相等,那麼對這兩個物件中的任一物件上呼叫 hashCode 方法不 要求一定生成不同的整數結果。但是,程式設計師應該意識到,為不相等的物件生成不同整數結果可以提高雜湊表的效能。

實現方法如下:
該需求就要重寫euqals方法,並且不能重寫hashcode方法,並使用hashset實現。把所有的超人放到一個hashset中去,迴圈遍歷set,呼叫change方法,通知變身,這就是所謂的觀察者模式。
當使用觀察者模式時,即使觀察的物件重寫了equals方法,使用了Hashset,也必須不能重寫hashcode方法,否則會有物件觀測不到通知
支援(0)反對(0)
#6樓 2018-04-21 13:57 夢幻怪獸
hashcode和equals具體是否同步,沒有規定,JVM只是說明使用集合的時候需要考慮這兩個同步性的問題。同步與不同步,最終會有兩種不同現象,具體那種是你需要的,無人知曉,所以不能一概而論
如果需要深入理解hashcode和equals,可以看這裡
https://blog.csdn.net/menghuanguaishou/article/details/80025647

· 兩個物件值相同(x.equals(y)==true),但卻可有不同的hashcode這句話對嗎?
· 兩個物件值同樣(x.equals(y) == true),但卻可有不同的hash code,這句話對不正確?
· 【Java面試題】41 兩個物件值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
· 兩個物件用equals方法比較為true,它們的Hashcode值相同嗎?
· 兩個物件值相同,有相同的hash code