2013-05-06 158 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中,当桶大小变大时,他们转而使用树形图。

相关问题