IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

关于hashcode 里面 使用31 系数的问题

淘宝网通用产品团队博客 2012-03-19 23:39:29 累计浏览 2,277 次
本机暂存

       首先我们来了解一下hashcode,什么是hashcode?有什么作用?

    hashcode其实就是散列码,使用hashcode使用高效率的哈希算法来定位查找对象!

    我们在使用容器来存储数据的时候会计算一串散列码,然后将数据放入容器。

    如:String s =“java”,那么计算机会先计算散列码,然后放入相应的数组中,数组的索引就是从散列吗计算来的,然后再装入数组里的容器里,如List.这就相当于把你要存的数据分成了几个大的部分,然后每个部分存了很多值, 你查询的时候先查大的部分,再在大的部分里面查小的,这样就比先行查询要快很多!

    一个对象的HashCode就是一个简单的Hash算法的实现,虽然它和那些真正的复杂的!Hash算法相比还不能叫真正的算法,但如何实现它,不仅仅是程序员的编程水平问题, 而是关系到你的对象在存取时性能的非常重要的问题.有可能,不同HashCode可能 会使你的对象存取产生成百上千倍的性能差别!

    java String在打印这个类型的实例对象的时候总是显示为下面的形式

    test.Test$tt@c17164

    上面test.Test是类名$tt是我自己写的内部类,而@后面这一段是什么呢?他其实就是tt这个实例类的hashcode是的16进制!

    它使用了Object 里面的toString()方法

Java代码
  • return getClass().getName() + “@” + Integer.toHexString(hashCode());  
  •     继续看看java里 String hashcode的源码:

    Java代码
  • public int hashCode() {  
  •     int h = hash;  
  •         int len = count;  
  •     if (h == 0 && len > 0) {  
  •         int off = offset;  
  •         char val[] = value;  
  •   
  •             for (int i = 0; i < len; i++) {  
  •                 h = 31*h + val[off++];  
  •             }  
  •             hash = h;  
  •         }  
  •         return h;  
  •     }  
  •     其实上面的实现也就是数学里:

    Java代码
  • s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]  
  •     的实现!我们会注意那个狗血的31这个系数为什么总是在里面乘来乘去?为什么不适用32或者其他数字?

        大家都知道,计算机的乘法涉及到移位计算。当一个数乘以2时,就直接拿该数左移一位即可!选择31原因是因为31是一个素数!

        所谓素数:

        质数又称素数

         。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。

        素数在使用的时候有一个作用就是如果我用一个数字来乘以这个素数,那么最终的出来的结果只能被素数本身和被乘数还有1来整除!如:我们选择素数3来做系数,那么3*n只能被3和n或者1来整除,我们可以很容易的通过3n来计算出这个n来。这应该也是一个原因!

        在存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“冲突”。如果使用相同hash地址的数据过多,那么这些数据所组成的

         hash链就更长,从而降低了查询效率!所以在选择系数的时候要选择尽量长的系数并且让乘法尽量不要溢出的系数,因为如果计算出来的hash地址越大,所

         谓的“冲突”就越少,查找起来效率也会提高。

        31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化,使用31的原因可能是为了更好的分配hash地址,并且31只占用5bits!

        在java乘法中如果数字相乘过大会导致溢出的问题,从而导致数据的丢失.

        而31则是素数(质数)而且不是很长的数字,最终它被选择为相乘的系数的原因不过与此!

        参考文档:http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/

        http://www.cogs.susx.ac.uk/courses/dats/notes/html/node114.html

        有待继续研究>>>>

    同分类推荐文章

    1. 对基本有序的序列排序算法 (2026-06-11 17:46:49)
    2. Four Levels Of Customer Understanding (2026-05-22 21:00:00)
    3. 除法的意义 (2026-04-12 20:52:17)

    查看更多 算法 文章 →

    建议继续学习

    1. SmartSprites - 命令行形式的CSS Sprites生成器 (累计阅读 123,894)
    2. Java开发岗位面试题归类汇总 (累计阅读 22,155)
    3. android 开发入门 (累计阅读 19,527)
    4. Linus:利用二级指针删除单向链表 (累计阅读 13,247)
    5. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
    6. HashMap解决hash冲突的方法 (累计阅读 12,652)
    7. 一个大二学生有关如何成为一名软件工程师的疑问及答复 (累计阅读 9,178)
    8. Java程序员应该知道的10个eclipse调试技巧 (累计阅读 8,011)
    9. 如何让员工忠于公司? (累计阅读 7,938)
    10. Java技术路线 (累计阅读 7,725)