hashCode就是我们所说的散列码,使用hashCode算法可以帮助我们进行高效率的查找,例如HashMap,说hashCode之前,先来看看Object类。

Java程序中所有类的直接或间接父类,处于类层次的最高点。在Object类里定义了很多我们常见的方法,包括我们要讲的hashCode方法,如下

Java代码  
  1. public final native Class<?> getClass();
  2. public native int hashCode();
  3. public boolean equals(Object obj) {
  4. return (this == obj);
  5. }
  6. public String toString() {
  7. return getClass().getName() + "@" +  Integer.toHexString(hashCode());
  8. }

在 java的很多类中都会重写equals和hashCode方法,这是为什么呢?最常见的String类,比如我定义两个字符相同的字符串,那么对它们进 行比较时,我想要的结果应该是相等的,如果你不重写equals和hashCode方法,他们肯定是不会相等的,因为两个对象的内存地址不一样。

String类的重写的hashCode方法

Java代码  
  1. public int hashCode() {
  2. int h = hash;
  3. if (h == 0) {
  4. int off = offset;
  5. char val[] = value;
  6. int len = count;
  7. for (int i = 0; i < len; i++) {
  8. h = 31*h + val[off++];
  9. }
  10. hash = h;
  11. }
  12. return h;
  13. }

1、这段代码究竟是什么意思?

其实这段代码是这个数学表达式的实现

Java代码  
  1. s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

s[i] 是string的第i个字符,n是String的长度。那为什么这里用31,而不是其它数呢?《Effective Java》是这样说的:之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的 好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化。

2、它返回的hashCode有什么特点呢?

可 以看到,String类是用它的value值作为参数来计算hashCode的,也就是说,相同的value就一定会有相同的hashCode值。这点也 很容易理解,因为value值相同,那么用equals比较也是相等的,equals方法比较相等,则hashCode一定相等。反过来不一定成立。它不 保证相同的hashCode一定有相同的对象。

一个好的hash函数应该是这样的:为不相同的对象产生不相等的hashCode。


理想情况下,hash函数应该把集合中不相等的实例均匀分布到所有可能的hashCode上,要想达到这种理想情形是非常困难的,至少java没有达到。
因为我们可以看到,hashCode是非随机生成的,它有一定的规律,就是上面的数学等式,我们可以构造一些具有相同hashCode但value值不一
样的,比如说:Aa和BB的hashCode是一样的。


到这里,你可能会想,原来构造hash冲突那么简单啊,那我是不是可以对HashMap函数构造很多<key,value>不都一样,但具有
相同的hashCode,这样的话可以把HashMap函数变成一条单向链表,运行时间由线性变为平方级呢?虽然HashMap重写的hashCode方
法比String类的要复杂些,但理论上说是可以这么做的。这也是最近比较热门的Hash
Collision DoS事件。

Java代码  
  1. public final int hashCode() {
  2. return (key==null   ? 0 : key.hashCode()) ^
  3. (value==null ? 0 : value.hashCode());

  4. (转载请注明出处:[url=http://www.k8764.com]博彩通[/url]

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

String的hashcode(java)的更多相关文章

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

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

  2. String.Format in Java and C#

    原文:String.Format in Java and C# JDK1.5中,String类新增了一个很有用的静态方法String.format(): format(Locale l, String ...

  3. String 转化成java.sql.Date和java.sql.Time

    String类型转换成java.sql.Date类型不能直接进行转换,首先要将String转换成java.util.Date,在转化成java.sql.Date 请点击--->   java架构 ...

  4. Java EE之Struts2异常[No mapping found for dependency [type=java.lang.String, name='actionPackages'#java.lang.RuntimeException]【摘抄】

    本博文摘自:http://www.blogjava.net/nkjava/archive/2009/03/29/262705.html 出现这个问题,可能是添加了struts2-codebehind包 ...

  5. 【spring boot】spring boot 前台GET请求,传递时间类型的字符串,后台无法解析,报错:Failed to convert from type [java.lang.String] to type [java.util.Date]

    spring boot 前台GET请求,传递时间类型的字符串,后台无法解析,报错:Failed to convert from type [java.lang.String] to type [jav ...

  6. String 不变性以及 Java 值传递和引用传递

    String 不变性以及 Java 值传递和引用传递 public class Example { String str = new String("good"); char[] ...

  7. java.lang.NumberFormatException: For input string: "1" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang

    java.lang.NumberFormatException: For input string: "1" at java.lang.NumberFormatException ...

  8. JSON的String字符串与Java的List列表对象的相互转换

    1.JSON的String字符串与Java的List列表对象的相互转换 在前端: 1.如果json是List对象转换的,可以直接遍历json,读取数据. 2.如果是需要把前端的List对象转换为jso ...

  9. org.hibernate.TypeMismatchException: Provided id of the wrong type for class cn.itcast.entity.User. Expected: class java.lang.String, got class java.lang.Integer at org.hibernate.event.internal.Defau

    出现org.hibernate.TypeMismatchException: Provided id of the wrong type for class cn.itcast.entity.User ...

随机推荐

  1. 使用openface(linux)

    在github上搜索openface,clone下来; 按照requirement.txt中安装需要的项: sudo apt-get install .... sudo pip install ... ...

  2. python 线程之_thread

    python 线程之_thread _thread module: 基本用法: def child(tid): print("hello from child",tid) _thr ...

  3. 20145223《Java程序设计》第5周学习总结

    20145223 <Java程序设计>第5周学习总结 教材学习内容总结 ·由于在编程的时候会遇到因各种原因而导致的错误,于是我们可以使用"try"."catc ...

  4. iOS UIImageView用代码添加点击事件

    image.userInteractionEnabled = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]ini ...

  5. matlab绘图--线性规划图解法示意

    matlab绘图--线性规划图解法示意 图解法 matlab绘图 区域填充 线性规划问题: matlab绘图 L1=[4,0;4,4];  plot(L1(:,1),L1(:,2));hold on  ...

  6. [linux]unixODBC的安装配置说明

    什么是unixODBC: ODBC(Open Database Connect)是由Microsoft 公司于1991 年提出的一个开放的,用于访问数据库的统一接口规范. unixODBC的是为非Wi ...

  7. JS保留小数点(四舍五入、四舍六入)实例

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  8. web移动端性能调优及16ms优化

    本文只是一个索引,收集了网络上大部分关于调试及优化方面的文章,从中挑选了一些比较好的文章分享给大家. 移动端性能不及桌面浏览器性能的10分之1,特别是在android设备良莠不齐的情况下,性能显得尤为 ...

  9. 【BZOJ】3670: [Noi2014]动物园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意:太水了= = #include <bits/stdc++.h> using ...

  10. Android -- 简单的图片浏览器

    1. 效果图