下面是求HashCode的一段代码,请高手能解释一下这种算法的原理与优点
public int hashCode() 

  if (this.hashValue == 0) 
  { 
    int result = 17; 
    int idValue = this.getId() == null ? 0 : this.getId().hashCode(); 
    result = result * 37 + idValue; 
    this.hashValue = result; 
  } 
  return this.hashValue; 

解决方案 »

  1.   


     // hashCode为每一个对象生成一个散列码 
     // 一般为关键属性乘以一个质数 
     /*
    在java的集合中,判断两个对象是否相等的规则是: 
    1,判断两个对象的hashCode是否相等 
    如果不相等,认为两个对象也不相等,完毕 
    如果相等,转入2 
    2,判断两个对象用equals运算是否相等 
    如果不相等,认为两个对象也不相等 
    如果相等,认为两个对象相等 
    */
    // hashcode方法不保证为不同的对象必然生成不同的hash码 
    // 如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。 
                      // 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
     这个不叫什么算法吧,重写hashcode()的同时一般也要重写equals()方法,两者配合进行对象的比较(一般针对自定义的java对象)
      

  2.   

    一般hashCode和equals配合使用的,判断两个实体是否相等,所以一般应该根据应用来决定hashCode和equals的实现吧,如果根本不关心两个实体是否相等,那么就不需要重写他们,如果是和数据库相关的,一般是根据id来判断。
    而至于说hashCode的算法,简单而有效的方法应该就是这种利用多项式生成吧,最好加一个prime的数,主要是保证两个认为不相等的实体,不会相等。
      

  3.   

    hashcode要尽量保证不重复int result = 17; 
        int idValue = this.getId() == null ? 0 : this.getId().hashCode(); 
        result = result * 37 + idValue;  
    你这个代码是不是写错了,result*37不就是一个常数吗,有必要这么做吗?
      

  4.   

    好像是一种什么算法来的,那乘以多少加上多少的.为了不产生相同的hashCode值.
      

  5.   

       哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。    这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
       在java中,hashcode更像是被作为了一个对象的标识符(这么说不正确但是比较切合实际),在别的地方可能我们都看不到hashcode这个方法的作用,但是在容器中,他的价值就体现了,通过对象本身的hashcode运算直接得到了该对象在链表中的偏移量,提高了查找的速度。 
       之所以选择result*37,是因为它是一个奇素数,如果乘数是偶数,并且乘法溢出的话,则信息会丢失,因为与2相乘等价于移位运算。在一般情况下,使用素数的好处并不明显,但是习惯上使用素数来计算散列结果。” 
      

  6.   


    //在上班,大概写了下~应该问题不大!
    public int hashCode()  
    {  
      if (this.hashValue == 0)  
      {  
        int result = 17;  
        int idValue = this.getId() == null ? 0 : this.getId().hashCode();  //这里说明,假如this.getId() 返回的是NULL,说明它们的hashCode一样!假如不是null,那就调用this.getId()的hashCode方法!不知道这个是Integer还是String,这样保证假如ID一样,保证他们的hashcode一样!都是null也保证他们的hashcode一样!
        result = result * 37 + idValue;  //这里就不说了
        this.hashValue = result;  
      }  
      return this.hashValue;  
    }  
      

  7.   

    http://blog.csdn.net/anqini/archive/2008/05/02/2363713.aspx
    看看这里,又帮助!
      

  8.   

    一个以前的CSDN帖子
    http://topic.csdn.net/u/20070101/20/6315cbf9-43fd-485e-9bb8-47efa4cd0668.html
    搜索功能要利用起来,hoho~
      

  9.   

    我想知道的就是javazhuobin兄所言: 之所以选择result*37,是因为它是一个奇素数,如果乘数是偶数,并且乘法溢出的话,则信息会丢失,因为与2相乘等价于移位运算。在一般情况下,使用素数的好处并不明显,但是习惯上使用素数来计算散列结果我想明白的是为什么要乘37而不是别的数,初值为什么是17而不是别的数,最后结果为什么还要加上一个值
      

  10.   

    每一个对象有一个不同hashcode码,包含对象副本也是的.
    算法怎么实现就不知道.....有待研究
      

  11.   

    今天对hashcode又有了新认识。获益良多
      

  12.   

    不知道是一种什么算法,
    从表面上来看 只是对hashCode()做了一个不算复杂的重写。
    按照算法的规则来生成散列码
      

  13.   

     为什么HashCode对于对象是如此的重要?  一个对象的HashCode就是一个简单的Hash算法的实现,虽然它和那些真正的复杂的Hash算法相比还不能叫真正的算法,它如何实现它,不仅仅是程序员的编程水平问题,而是关系到你的对象在存取是性能的非常重要的关系.有可能,不同的HashCode可能会使你的对象存取产生,成百上千倍的性能差别。  我们先来看一下,在JAVA中两个重要的数据结构:HashMap和Hashtable,虽然它们有很大的区别,如继承关系不同,对value的约束条件(是否允许null)不同,以及线程安全性等有着特定的区别,但从实现原理上来说,它们是一致的.所以,我们只以Hashtable来说明:  在java中,存取数据的性能,一般来说当然是首推数组,但是在数据量稍大的容器选择中,Hashtable将有比数组性能更高的查询速度.具体原因看下面的内容。  Hashtable在存储数据时,一般先将作为key的对象的HashCode和0x7FFFFFFF做与操作,因为一个对象的HashCode可以为负数,这样操作后可以保证它为一个正整数.然后以Hashtable的长度取模,得到值对象在Hashtable中的索引。  index = (o.hashCode() & 0x7FFFFFFF)%hs.length;这个值对象就会直接放在Hashtable的第index位置,对于写入,这和数组一样,把一个对象放在其中的第index位置,但如果是查询,经过同样的算法,Hashtable可以直接通过key得到index,从第index取得这个值对象,而数组却要做循环比较.所以对于数据量稍大时,Hashtable的查询比数据具有更高的性能。  虽然不同对象有不同的hashcode,但不同的hashCode经过与长度的取余,就很可能产生相同的index。  极端情况下会有大量的对象产生一个相同的索引.这就是关系Hashtable性能问题的最重要的问题:  Hash冲突。  常见的Hash冲突是不同key对象最终产生了相同的索引,而一种非常甚至绝对少见的Hash冲突是,如果一组对象的个数大过了int范围,而HashCode的长度只能在int范围中,所以肯定要有同一组的元素有相同的HashCode,这样无论如何他们都会有相同的索引.当然这种极端的情况是极少见的,可以暂不考虑,但是对于同的HashCode经过取模,则会产中相同的索引,或者不同的对象却具有相同的HashCode,当然具有相同的索引。  事实上一个设计各好的HashTable,一般来说会比较平均地分布每个元素,因为Hashtable的长度总是比实际元素的个数按一定比例进行自增(装填因子一般为0.75)左右,这样大多数的索引位置只有一个对象,而很少的位置会有几个元素.所以Hashtable中的每个位置存放的是一个链表,对于只有一个对象是位置,链表只有一个首节点(Entry),Entry的next为null.然后有hashCode,key,value属性保存了该位置的对象的HashCode,key和value(对象本身),如果有相同索引的对象进来则会进入链表的下一个节点.如果同一个索引中有多个对象,根据HashCode和key可以在该链表中找到一个和查询的key相匹配的对象。  从上面我看可以看到,对于HashMap和Hashtable的存取性能有重大影响的首先是应该使该数据结构中的元素尽量大可能具有不同的HashCode,虽然这并不能保证不同的HashCode产生不同的index,但相同的HashCode一定产生相同的index,从而影响产生Hash冲突。  对于一个象,如果具有很多属性,把所有属性都参与散列,显然是一种笨拙的设计.因为对象的HashCode()方法几乎无所不在地被自动调用,如equals比较,如果太多的对象参与了散列.那么需要的操作常数时间将会增加很大.所以,挑选哪些属性参与散列绝对是一个编程水平的问题。  从实现来说,一般的HashCode方法会这样:  return Attribute1.HashCode() + Attribute1.HashCode()..[+super.HashCode()]。  我们知道,每次调用这个方法,都要重新对方法内的参与散列的对象重新计算一次它们的HashCode的运算,如果一个对象的属性没有改变,仍然要每次都进行计算,所以如果设置一个标记来缓存当前的散列码,只要当参与散列的对象改变时才重新计算,否则调用缓存的hashCode,这可以从很大程度上提高性能。  默认的实现是将对象内部地址转化为整数作为HashCode,这当然能保证每个对象具有不同的HasCode,因为不同的对象内部地址肯定不同(废话),但java语言并不能让程序员获取对象内部地址,所以,让每个对象产生不同的HashCode有着很多可研究的技术。  如果从多个属性中采样出能具有平均分布的hashCode的属性,这是一个性能和多样性相矛盾的地方,如果所有属性都参与散列,当然hashCode的多样性将大大提高,但牺牲了性能,而如果只能少量的属性采样散列,极端情况会产生大量的散列冲突,如对"人"的属性中,如果用性别而不是姓名或出生日期,那将只有两个或几个可选的hashcode值,将产生一半以上的散列冲突.所以如果可能的条件下,专门产生一个序列用来生成HashCode将是一个好的选择(当然产生序列的性能要比所有属性参与散列的性能高的情况下才行,否则还不如直接用所有属性散列)。  如何对HashCode的性能和多样性求得一个平衡,可以参考相关算法设计的书,其实并不一定要求非常的优秀,只要能尽最大可能减少散列值的聚集.重要的是我们应该记得HashCode对于我们的程序性能有着生要的影响,在程序设计时应该时时加以注意。
      

  14.   

    怎么没有人说话了呢我想知道的就是javazhuobin兄所言:  之所以选择result*37,是因为它是一个奇素数,如果乘数是偶数,并且乘法溢出的话,则信息会丢失,因为与2相乘等价于移位运算。在一般情况下,使用素数的好处并不明显,但是习惯上使用素数来计算散列结果 我想明白的是为什么要乘37而不是别的数,初值为什么是17而不是别的数,最后结果为什么还要加上一个值 
      

  15.   

    其实你用eclipse的话可以自动生成hascode()和equals()代码的.
    我想问下hascode判断相等有什么关系么?
      

  16.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【LMXEQ5】截止到2008-07-07 10:04:10的历史汇总数据(不包括此帖):
    发帖的总数量:4                        发帖的总分数:100                      
    结贴的总数量:3                        结贴的总分数:50                       
    无满意结贴数:2                        无满意结贴分:120                      
    未结的帖子数:1                        未结的总分数:50                       
    结贴的百分比:75.00 %               结分的百分比:50.00 %                  
    无满意结贴率:66.67 %               无满意结分率:240.00%                  
    楼主加油