Java中String的hash函数分析
转载自:http://blog.csdn.net/hengyunabc/article/details/7198533
JDK6的源码:
- /**
- * Returns a hash code for this string. The hash code for a
- * <code>String</code> object is computed as
- * <blockquote><pre>
- * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
- * </pre></blockquote>
- * using <code>int</code> arithmetic, where <code>s[i]</code> is the
- * <i>i</i>th character of the string, <code>n</code> is the length of
- * the string, and <code>^</code> indicates exponentiation.
- * (The hash value of the empty string is zero.)
- *
- * @return a hash code value for this object.
- */
- public int hashCode() {
- int h = hash;
- if (h == 0) {
- int off = offset;
- char val[] = value;
- int len = count;
- for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
- }
- hash = h;
- }
- return h;
- }
以字符串"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值的:
- public class Name{
- String firstName;
- String lastName;
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result
- + ((firstName == null) ? 0 : firstName.hashCode());
- result = prime * result
- + ((lastName == null) ? 0 : lastName.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Name other = (Name) obj;
- if (firstName == null) {
- if (other.firstName != null)
- return false;
- } else if (!firstName.equals(other.firstName))
- return false;
- if (lastName == null) {
- if (other.lastName != null)
- return false;
- } else if (!lastName.equals(other.lastName))
- return false;
- return true;
- }
- }
可见,还是以31为倍数, hashCode = firstName.hashCode() * 31 + lastName.hashCode() 。
BTW:Java的字符串的hash做了缓存,第一次才会真正算,以后都是取缓存值。
eclipse生成的equals函数质量也很高,各种情况都考虑到了。
总结:字符串hash函数,不仅要减少冲突,而且要注意相同前缀的字符串生成的hash值要相邻。
Java中String的hash函数分析的更多相关文章
- Java中String连接性能的分析【转】
[转]http://www.blogjava.net/javagrass/archive/2010/01/24/310650.html 总结:如果String的数量小于4(不含4),使用String. ...
- Java中String连接性能的分析
总结:如果String的数量小于4(不含4),使用String.concat()来连接String,否则首先计算最终结果的长度,再用该长度来创建一个StringBuilder,最后使用这个String ...
- Java中String的替换函数:replace与replaceAll的区别
例如有如下x的字符串 String x = "[kllkklk\\kk\\kllkk]"; 要将里面的"kk"替换为++,可以使用两种方法得到相同的结果 r ...
- java中string.trim()函数的使用
java中string.trim()函数的的作用是去掉字符串开头和结尾的空格,防止不必要的空格导致的错误. public static void main(String arg[]){ String ...
- OC与c混编实现Java的String的hashcode()函数
首先,我不愿意大家需要用到这篇文章里的代码,因为基本上你就是被坑了. 起因:我被Java后台人员坑了一把,他们要对请求的参数增加一个额外的字段,字段的用途是来校验其余的参数是否再传递过程中被篡改或因为 ...
- java中String类型变量的赋值问题
第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...
- 探秘Java中String、StringBuilder以及StringBuffer
探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...
- java中String类、StringBuilder类和StringBuffer类详解
本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html 版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...
- 【转载】 Java中String类型的两种创建方式
本文转载自 https://www.cnblogs.com/fguozhu/articles/2661055.html Java中String是一个特殊的包装类数据有两种创建形式: String s ...
随机推荐
- 以太坊开发(二)使用Ganache CLI在私有链上搭建智能合约
以太坊开发(二)使用Ganache CLI在私有链上搭建智能合约 在上一篇文章中,我们使用Truffle自带的客户端Truffle Develop,在私有链上搭建并运行了官方提供的WebPack智能合 ...
- 常用linux命令相关
[查看端口] netstat -tlnp netstat命令 netstat -an | grep 3306 3306替换成需要grep的端口号 lsof命令 通过list open file命令可以 ...
- 在Excel里面,单元格里输入公式后只显示公式本身,不显示结果,怎么办
这种情况是对Excel进行了设置,设置的就是在单元格中只显示公式,不显示结果,解决的办法有两个: 1 用快捷键CTR+~ 2 点击"公式"选项卡,然后反选里面的"显示公式 ...
- Android - 时间 日期相关组件
源码下载地址 : -- CSDN : http://download.csdn.net/detail/han1202012/6856737 -- GitHub : https://github.co ...
- UBUNTU如何安装tar.gz版的flash
adobe flash player的官方下载页面为:https://get.adobe.com/cn/flashplayer/ 不过近期通过APT方式以及ubuntu的软件中心都安装不了flashp ...
- LintCode-67.二叉树的中序遍历
二叉树的中序遍历 给出一棵二叉树,返回其中序遍历. 样例 给出一棵二叉树 {1,#,2,3}, 返回 [1,3,2]. 挑战 你能使用非递归实现么? 标签 递归 二叉树 二叉树遍历 code /** ...
- js实现倒计时60秒的简单代码
<!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...
- 检测固定IP的端口是否开放批出
因为运维工作经常需要telnet某个IP的端口是否正常,因此有了下文 .BAT内容如下: @echo off for /f %%i in ('type ip.txt') do ( echo %%i t ...
- vector中数据进行去重和排序
, , , , , , ,}; std::vector<int> vec(a, a+sizeof(a)/sizeof(int) ); std::sort(vec.begin(), vec. ...
- mysql 重置 root 密码
mysqld_safe --skip-grant-tables & UPDATE mysql.user SET authentication_string=PASSWORD('mima') W ...