散列计算就是计算元素应该放在数组的哪个元素里。准确的说是放到哪个链表里面。按照Java的规则,如果你要想将一个对象放入HashMap中,你的对象的类必须提供hashcode方法,返回一个整数值。比如String类就有如下方法:

  1. publicint int int if && len > ) {
  2. int char forint; i < len; i++) {
  3. *h + val[off++];
  4. return     }

注意上面的for循环,有点搞吧?我来举个例子,让你很容易明白它在搞什么名堂。比如有一个字符串“abcde”,采用31进制的计算方法来计算这个字符串的总和,你会写出下面的计算式子:
a*31^4+b*31^3+c*31^2+d*31^1+e*31^0.注意,这里的a,b,c,d或者e指的是它们的ASCII值。很有趣的循环,居然可以用来算N进制。这个循环可以抽出来单独作为计算进制的好工具:

  1. publicstaticvoid
    int,};
  2. ,a));
  3. privatestaticintintint
    int;
  4. forint;i<a.length;++i){
  5. return
        }

静态方法caculate接受radix作为进制基数,数组a模拟要计算的进制的数字,只是注意表面顺序需要一致。比如 01 二进制串,在数组中要按照{0,1}排列。上面的输出结果是1,符合01的真实值。
  那么为什么选用31作为基数呢?先要明白为什么需要HashCode.每个对象根据值计算HashCode,这个code大小虽然不奢求必须唯一(因为这样通常计算会非常慢),但是要尽可能的不要重复,因此基数要尽量的大。另外,31*N可以被编译器优化为
左移5位后减1,有较高的性能。其实选用31还是有争议,反对者(参考http://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier)
认为这个东西还是会导致较多的重复,应该用更大的数字。所以,或许将来Java的实现中会有所变化。下面这篇文章介绍了两个结论:
1.基数要用质数
质数的特性(只有1和自己是因子)能够使得它和其他数相乘后得到的结果比其他方式更容易产成唯一性,也就是hash code值的冲突概率最小。
2.选择31是观测分布结果后的一个选择,不清楚原因,但的确有利。

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

另外,String.hashCode内部会缓存第一次计算的值,因为这是一个final(不可变)类,也就是String对象的内容是不会变的。这能够在多次put到HashMap的场合提高性能,不过似乎用处不多。

转:为什么在定义hashcode时要使用31这个数呢?的更多相关文章

  1. 为什么在定义hashcode时要使用31这个数呢?

    散列计算就是计算元素应该放在数组的哪个元素里.准确的说是放到哪个链表里面.按照Java的规则,如果你要想将一个对象放入HashMap中,你的对象的类必须提供hashcode方法,返回一个整数值. ht ...

  2. 在php中定义常量时,const与define的区别?

    问]在php中定义常量时,const与define的区别?  [答]使用const使得代码简单易读,const本身就是一个语言结构,而define是一个函数.另外const在编译时要比define快很 ...

  3. PHP 中 define() 和 const 定义常量时的区别

    自 PHP 5.3.0 起,有两种方式定义常量,使用 const 关键字或者 define() 函数:   1 2 const FOO = 'BAR'; define('FOO', 'BAR'); 这 ...

  4. JavaScript 中定义变量时有无var声明的区别

    关于JavaScript中定义变量时有无var声明的区别 var a=5; //正确 a=5; //正确 在javascript中,以上两种方法都是定义变量的正确方法.微软的Script56.CHM中 ...

  5. python定义函数时的默认返回值

    python定义函数时,一般都会有指定返回值,如果没有显式指定返回值,那么python就会默认返回值为None, 即隐式返回语句: return None 执行如下代码 def now(): prin ...

  6. python定义函数时默认参数注意事项

    如果在调用一个函数时,没有传递默认参数,则函数内的默认参数是对函数的默认参数属性__defaults__的引用, 如 def func(arg1=[]): arg1.append(2) 调用func时 ...

  7. PHP定义字符串时单引号和双引号的区别

    一般用单引号或双引号标识一个字符串.单引号串与双引号串,在PHP中的处理是不同的.双引号中的内容可以被解释并被替换,单引号串中的内容则被作为普通字符处理. 例如: $str=6; echo " ...

  8. python定义函数时的参数&调用函数时的传参

    一.定义函数: 1.位置参数:直接定义参数 2.默认参数(或者关键字参数):参数名 = "默认值" 3.位置参数必须在默认参数之前 二.调用函数: 1.按位置传,直接写参数的值 2 ...

  9. 【转载】最近在用Arrays的asList()生成的List时,List元素的个数时而不正确,数组转化为List,即Arrays.asList(intArray);

    最近在用Arrays的asList()生成的List时,List元素的个数时而不正确. Java代码 //经多次测试,只要传递的基本类型的数组,生成List的元素个数均为1 char arrc = { ...

随机推荐

  1. 在mesh client示例中加入spi_slave接口(without IDE)

    在mesh client示例中加入spi_slave接口(without IDE) 主要是理解cmake构建的过程,然后修改工程中的inlcude路径及c源文件. 1. 解压mesh_sdk unzi ...

  2. KVM存储虚拟化---玩转openstack

    KVM 的存储虚拟化是通过存储池(Storage Pool)和卷(Volume)来管理的. Storage Pool 是宿主机上可以看到的一片存储空间,可以是多种类型,后面会详细讨论.Volume 是 ...

  3. SPOJ 694 Distinct Substrings/SPOJ 705 New Distinct Substrings(后缀数组)

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

  4. 第四次作业之psp

    psp 进度条 博文字数累积折线图 代码行数累积折线图 psp饼状图

  5. UCP协议

    UDP只在ip数据报的服务上增加了一点功能,就是复用和分用还有差错检验的功能 (1)UDP是面向无连接:发送之前不需要建立连接,减少了时间延续 (2)UDP只是尽最大努力交付,不能保证无措 (3)UD ...

  6. 理解windows模型

    同步 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等).但是一般而言,我们在说同步.异步的时候,特指 ...

  7. 3dContactPointAnnotationTool开发日志(二十)

      为了使工具更人性化,我又在每个status的text上绑了个可以拖拽实现值改变的脚本,但是不知道为啥rotx那个值越过+-90范围后连续修改就会产生抖动的现象,试了很多方法也没能弄好,不过实际用起 ...

  8. PokeCats开发者日志(十)

      现在是PokeCats游戏开发的第三十三天的中午,收到了中国版权保护中心软件登记部发来的受理通知书.   上易版权看一眼,貌似离拿证不远了.   想一想还有点小激动呢!

  9. 基于3D卷积神经网络的人体行为理解(论文笔记)(转)

    基于3D卷积神经网络的人体行为理解(论文笔记) zouxy09@qq.com http://blog.csdn.net/zouxy09 最近看Deep Learning的论文,看到这篇论文:3D Co ...

  10. vuex介绍--一篇看懂vuejs的状态管理神器

    原文,请点击此链接http://www.ituring.com.cn/article/273487