2013-05-06 179 views
11

hashCode()和equals()方法的概念是兩個不相等的對象具有相同的散列碼

1)如果兩個對象是根據等於()相等,則調用每個這兩個對象的哈希碼方法應該產生相同的哈希碼。

,另一個是

2)不要求是,如果兩個對象根據等於()是不相等的,然後調用散列碼方法對每個所述兩個對象都必須產生不同的值。

我嘗試並理解第一個,這是第一點的代碼。

public class Test { 
    public static void main(String[] args) { 

     Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
     map.put(1, 11); 
     map.put(4, 11); 
     System.out.println(map.hashCode()); 
     Map<Integer, Integer> map1 = new HashMap<Integer, Integer>(); 
     map1.put(1, 11); 
     map1.put(4, 11); 
     System.out.println(map1.hashCode()); 
     if (map.equals(map1)) { 
      System.out.println("equal "); 
     } 
    } 
} 

上述程序爲兩個不同的對象提供相同的哈希碼。

有人可以用一個例子來解釋我,根據equals()不同的兩個不同對象怎麼能有相同的散列碼。

+6

比較的可能散列碼的數目可能'Long's或'String's的數目。 http://en.wikipedia.org/wiki/Pigeonhole_principle – SLaks 2013-05-06 14:19:29

+0

可能的重複[在Java中==,equals和hashcode的示例](http://stackoverflow.com/questions/2731889/example-of-equals-and- hashcode-in-java) – cHao 2013-05-06 14:21:56

回答

19

2一個hashCode)是不需要,如果兩個對象不等根據等(),然後在這兩個對象的每一個上調用hashcode方法都必須產生不同的值。

根據散列函數,2個不同的對象可以具有相同的散列碼。然而,兩個相同的對象必須在散列時產生相同的結果(除非某人在隨機數中實現散列函數,在這種情況下它沒用)

例如,如果我是散列整數,而我的散列函數只是(n % 10)那麼數字17和數字27將產生相同的結果。這並不意味着這些數字是相同的。

6

hashCode()有32位可能的值。你的對象可以有更多的不同,所以你將有一些具有相同hashCode的對象,即你不能確保它們是唯一的。

這在有限大小的散列集合中變得更糟。 HashMap的最大容量爲1 < < 30或約10億。這意味着只有30位被真正使用,並且如果您的集合不使用16+ GB並且僅僅說出一千個存儲桶(或者技術上說是1 < < 10),那麼真的只有1000個可能的存儲桶。

注意:在HotSpot JVM上,默認的Object.hashCode()永遠不會是負數,即只有31位,儘管我不知道爲什麼。

如果你想用相同的hashCode生成很多對象看看Long。

// from Long 
public int hashCode() { 
    return (int)(value^(value >>> 32)); 
} 

for(long i = Integer.MIN_VALUE; i < Integer.MAX_VALUE;i++) { 
    Long l = (i << 32) + i; 
    System.out.print(l.hashCode()+" "); 
    if (i % 100 == 0) 
     System.out.println(); 
} 

這將產生4個十億龍所有的0

+3

如果你想用相同的hashCode生成大量對象,重寫「public int hashChode()」返回相同的hashCode會不會更簡單。這不是最終的。 – emory 2013-05-06 14:48:37

6

實施例與字符串(所有的字符串下面具有0的哈希碼):

public static void main(String[] args) { 
    List<String> list = Arrays.asList("pollinating sandboxes", 
             "amusement & hemophilias", 
             "schoolworks = perversive", 
             "electrolysissweeteners.net", 
             "constitutionalunstableness.net", 
             "grinnerslaphappier.org", 
             "BLEACHINGFEMININELY.NET", 
             "WWW.BUMRACEGOERS.ORG", 
             "WWW.RACCOONPRUDENTIALS.NET", 
             "Microcomputers: the unredeemed lollipop...", 
             "Incentively, my dear, I don't tessellate a derangement.", 
             "A person who never yodelled an apology, never preened vocalizing transsexuals."); 
    for (String s : list) { 
     System.out.println(s.hashCode()); 
    } 
} 

(從this post被盜)。

+0

+1我正在考慮這篇文章;) – 2013-05-06 14:22:51

-1

我的理解是,hashCode是內存地址的數字表示,但不是實際的地址。它可以被改變,而不影響實際的地址。因此,即使所有對象都是完全不同的東西,也應該可以將所有對象設置爲相同的hashCode。想想一個街區上的每個人都突然有相同的街道地址。他們是真正不同的人,但現在都擁有相同的街道地址。他們的房子沒有動,一個不正常的青少年只是把所有人都標記爲「100 N. Main」。

我對Java很新,所以請謹慎回答我的問題。

+0

這實際上是一個關於hashcode是什麼的完全不正確的想法。 – 2013-05-06 14:32:56

+0

什麼是更好的或正確的想法? – petematt62 2013-05-06 14:36:20

0

其實很簡單,

首先我們必須知道什麼是散列碼。

在java中,哈希碼很簡單,它是一種32位有符號整數,它以某種方式從相關數據中派生出來。整數類型通常只是(Int Data)Mod(一些合理的大素數)。

讓我們對整數做一個簡單的散列。
定義:

public int hash(int num){ return num % 19 ; } 

在這種情況下,既圖19和38將返回的0

散列值對於字符串類型,散列從單個字符導出並串中的每個位置的人,除以相當大的數字。 (或者,在Java的情況下,忽略32位和的溢出)。

鑑於可能存在任意多個字符串,並且字符串中存在有限數量的哈希碼(2^32),所以鴿子洞原則規定至少有兩個不同的字符串會導致相同的哈希碼。

0

hashCode的目的是使下面的公理和推論:

  • 如果一個碰巧知道兩個對象的哈希碼,而這些散列碼不匹配,一個不需要理會檢查對象進一步知道對象將不匹配。即使兩個任意選擇的非匹配對象具有10%的匹配哈希碼的機會,測試哈希碼也可以讓其中一個消除90%的比較結果。不如99.99%那樣大,但絕對值得。

  • 知道一堆中沒有任何對象具有特定哈希碼意味着該對象中沒有任何對象會將該對象與該哈希碼匹配。如果將一個對象集合分割成散列碼爲偶數和散列碼爲奇數的對象,並且想要查找是否有一個哈希碼恰好爲偶數的給定項目,則不需要檢查任何內容在奇數散列項目的集合中。同樣,不需要在偶數哈希集合中查找奇數哈希項。即使是雙值散列,也可以將搜索速度提高近一半。如果將一個集合分成較小的分區,則可以進一步加快速度。

注意hashCode()將提供最大的利益,如果每個不同的項目將返回不同的哈希,但是它可以提供巨大的好處,即使許多項目具有相同的哈希值。節省90%和節省99.99%之間的差異往往遠大於數據所表明的結果,因此,如果能合理輕鬆地將事情改善到99%,99.9%或更好的情況,應該這樣做,但是他之間的差異在一個集合中有零個錯誤匹配和幾個錯誤匹配是非常輕微的。

1

如果你知道如何實現HashMap並且它的目的非常簡單,哈希表需要大量的值,並將它們分成更小的集合(桶),以便更快地檢索元素。基本上,您只需要搜索一個存儲區而不是您的元素的完整列表。這些桶位於索引是散列碼的數組中。每個存儲桶包含具有相同散列碼的元素的鏈接列表,但不等於()。我認爲在Java 8中,當桶大小變大時,他們轉而使用樹形圖。

相關問題