转载自:http://blog.csdn.net/hengyunabc/article/details/7198533

JDK6的源码:

[java] view
plain
copy

  1. /**
  2. * Returns a hash code for this string. The hash code for a
  3. * <code>String</code> object is computed as
  4. * <blockquote><pre>
  5. * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
  6. * </pre></blockquote>
  7. * using <code>int</code> arithmetic, where <code>s[i]</code> is the
  8. * <i>i</i>th character of the string, <code>n</code> is the length of
  9. * the string, and <code>^</code> indicates exponentiation.
  10. * (The hash value of the empty string is zero.)
  11. *
  12. * @return  a hash code value for this object.
  13. */
  14. public int hashCode() {
  15. int h = hash;
  16. if (h == 0) {
  17. int off = offset;
  18. char val[] = value;
  19. int len = count;
  20. for (int i = 0; i < len; i++) {
  21. h = 31*h + val[off++];
  22. }
  23. hash = h;
  24. }
  25. return h;
  26. }

以字符串"123"为例:

字符'1'的ascii码是49

hashCode = (49*31 + 50)*31 + 51

或者这样看:

hashCode=('1' * 31 + '2' ) * 31 + '3'

可见实际可以看作是一种权重的算法,在前面的字符的权重大。

这样有个明显的好处,就是前缀相同的字符串的hash值都落在邻近的区间。

好处有两点:

1.可以节省内存,因为hash值在相邻,这样hash的数组可以比较小。比如当用HashMap,以String为key时。

2.hash值相邻,如果存放在容器,比好HashSet,HashMap中时,实际存放的内存的位置也相邻,则存取的效率也高。(程序局部性原理)

以31为倍数,原因了31的二进制全是1,则可以有效地离散数据。

最后看下,两个字符串,由Eclipse生成的代码是如何计算hash值的:

[java] view
plain
copy

  1. public class Name{
  2. String firstName;
  3. String lastName;
  4. @Override
  5. public int hashCode() {
  6. final int prime = 31;
  7. int result = 1;
  8. result = prime * result
  9. + ((firstName == null) ? 0 : firstName.hashCode());
  10. result = prime * result
  11. + ((lastName == null) ? 0 : lastName.hashCode());
  12. return result;
  13. }
  14. @Override
  15. public boolean equals(Object obj) {
  16. if (this == obj)
  17. return true;
  18. if (obj == null)
  19. return false;
  20. if (getClass() != obj.getClass())
  21. return false;
  22. Name other = (Name) obj;
  23. if (firstName == null) {
  24. if (other.firstName != null)
  25. return false;
  26. } else if (!firstName.equals(other.firstName))
  27. return false;
  28. if (lastName == null) {
  29. if (other.lastName != null)
  30. return false;
  31. } else if (!lastName.equals(other.lastName))
  32. return false;
  33. return true;
  34. }
  35. }

可见,还是以31为倍数, hashCode = firstName.hashCode() * 31 + lastName.hashCode() 。

BTW:Java的字符串的hash做了缓存,第一次才会真正算,以后都是取缓存值。

eclipse生成的equals函数质量也很高,各种情况都考虑到了。

总结:字符串hash函数,不仅要减少冲突,而且要注意相同前缀的字符串生成的hash值要相邻。

Java中String的hash函数分析的更多相关文章

  1. Java中String连接性能的分析【转】

    [转]http://www.blogjava.net/javagrass/archive/2010/01/24/310650.html 总结:如果String的数量小于4(不含4),使用String. ...

  2. Java中String连接性能的分析

    总结:如果String的数量小于4(不含4),使用String.concat()来连接String,否则首先计算最终结果的长度,再用该长度来创建一个StringBuilder,最后使用这个String ...

  3. Java中String的替换函数:replace与replaceAll的区别

    例如有如下x的字符串  String x = "[kllkklk\\kk\\kllkk]"; 要将里面的"kk"替换为++,可以使用两种方法得到相同的结果  r ...

  4. java中string.trim()函数的使用

    java中string.trim()函数的的作用是去掉字符串开头和结尾的空格,防止不必要的空格导致的错误. public static void main(String arg[]){ String ...

  5. OC与c混编实现Java的String的hashcode()函数

    首先,我不愿意大家需要用到这篇文章里的代码,因为基本上你就是被坑了. 起因:我被Java后台人员坑了一把,他们要对请求的参数增加一个额外的字段,字段的用途是来校验其余的参数是否再传递过程中被篡改或因为 ...

  6. java中String类型变量的赋值问题

    第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...

  7. 探秘Java中String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

  8. java中String类、StringBuilder类和StringBuffer类详解

    本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html  版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...

  9. 【转载】 Java中String类型的两种创建方式

    本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...

随机推荐

  1. 蓝桥杯算法训练 区间k大数查询

    算法训练 区间k大数查询   问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个 ...

  2. openstack多region介绍与实践---转

    概念介绍 所谓openstack多region,就是多套openstack共享一个keystone和horizon.每个区域一套openstack环境,可以分布在不同的地理位置,只要网络可达就行.个人 ...

  3. sqlserver 2008 merger语句

    Merge关键字是一个神奇的DML关键字.它在SQL Server 2008被引入,它能将Insert,Update,Delete简单的并为一句.MSDN对于Merge的解释非常的短小精悍:”根据与源 ...

  4. Alpha发布文案加美工展示

    目录 团队简介 项目进展 组内分工 队员总结 后期计划 一.团队简介 二.项目进展 从选题发布到今天的Alpha发布,我们团队经历了许许多多的磨难.我们最终设计了如下的功能:首页.班级.个人.更多.打 ...

  5. python切片详解

    先从原理上分析切片运算: list的切片,内部是调用__getitem__,__setitem__,__delitem__和slice函数.而slice函数又是和range()函数相关的. 给切片传递 ...

  6. 福大软工1816:Alpha(8/10)

    Alpha 冲刺 (8/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1. 2. 展示GitHub当 ...

  7. 【转】bind简单示例

    bind简单示例代码 namespace { class placeholder_ {}; placeholder_ __1; } template <typename R, typename ...

  8. lol佐伊美图

      心血来潮,分享一波从各个网站上搜集到的佐伊美图,持续更新!(最近更新日期:2019/03/17) Section1 暮光星灵 2018/11/16 2019/02/15 2019/03/17 Se ...

  9. RHEL 6.4(i386)安装MySQL 5.6的方法

  10. 使用js 复制 文字到剪贴板

    有一个好插件 https://clipboardjs.com/ 兼容性  IE9+ 一般基本够用,但如果非要兼容IE8 可使用IE 特有的 方法 window.clipboardData.setDat ...