下面的英文描述了String.hashCode()方法,在特定情况下,返回值为0的问题:

Java offers the HashMap and Hashtable classes, which use the 
String.hashCode() hash function. It is very similar to DJBX33A (instead of 33, it uses the 
multiplication constant 31 and instead of the start value 5381 it uses 0). Thus it is also 
vulnerable to an equivalent substring attack. When hashing a string, Java also caches the 
hash value in the hash attribute, but only if the result is different from zero. 
Thus, the target value zero is particularly interesting for an attacker as it prevents caching 
and forces re-hashing.

接下来我们来看一下String类的hashCode()方法:当下面代码中的val[off++]返回值都是0的情况下,hashCode()的返回值也是0

    public int hashCode() {
int h = hash;//初始值为0
if (h == 0 && count > 0) {//count值为字符个数
int off = offset;//off值为0
char val[] = value;//字符数组
int len = count; for (int i = 0; i < len; i++) {
h = 31*h + val[off++];//如果val[off++]的所有返回值都是ascii码0会发生什么?
}
hash = h;
}
return h;
}

我们知道hashmap存储值的数据结构是数组+链表的结果,如果不同的key值,但是返回的hashcode()值都是0的话,hashmap的结构不会得到很好的应用,会造成所有的元素都存储在数组的第一个元素的链表中,下面通过代码来证明:

package com.mantu.advance;

import java.util.HashMap;

public class Lesson10HashmapLeak {

    public static void main(String[] args){
testHashMapNormal();
testHashMapBug();
} public static void testHashMapBug(){
HashMap<String,String> map = new HashMap<String,String>(100000);
String xxx= asciiToString("0");
String temp = xxx;
long beginTime = System.currentTimeMillis();
//System.out.println("开始时间:"+System.currentTimeMillis());
for(int i=0;i<100000;i++){
map.put(xxx, i+""); if((i%10000)==0){
xxx=temp;
}
else{
xxx=xxx+temp;
}
}
System.out.println("testHashMapBug()耗时:"+(System.currentTimeMillis()-beginTime)+"毫秒");
} public static void testHashMapNormal(){
HashMap<String,String> map = new HashMap<String,String>(100000);
String xxx= asciiToString("1");
String temp = xxx;
long beginTime = System.currentTimeMillis();
//System.out.println("开始时间:"+System.currentTimeMillis());
for(int i=0;i<100000;i++){
map.put(xxx, i+""); if((i%10000)==0){
xxx=temp;
}
else{
xxx=xxx+temp;
}
}
System.out.println("testHashMapNormal()耗时:"+(System.currentTimeMillis()-beginTime)+"毫秒");
}
public static String asciiToString(String value)
{
StringBuffer sbu = new StringBuffer();
String[] chars = value.split(",");
for (int i = 0; i < chars.length; i++) {
sbu.append((char) Integer.parseInt(chars[i]));
}
return sbu.toString();
}
}

最后的执行结果是:

正常key值的一组执行时间是:1887毫秒

key值对应的hashcode()值为0的执行时间是:7365毫秒

lesson10:hashmap变慢原因分析的更多相关文章

  1. SELECT TOP 1 比不加TOP 1 慢的原因分析以及SELECT TOP 1语句执行计划预估原理

    本文出处:http://www.cnblogs.com/wy123/p/6082338.html 现实中遇到过到这么一种情况: 在某些特殊场景下:进行查询的时候,加了TOP 1比不加TOP 1要慢(而 ...

  2. HashMap多线程并发问题分析

    转载: HashMap多线程并发问题分析 并发问题的症状 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题. ...

  3. Beforeunload打点丢失原因分析及解决方案

    淘宝的鱼相在 2012 年 8 月份发表了一篇文章,里面讲述了他们通过一个月的数据采集试验,得到的结果是:如果在浏览器的本页面刷新之前发送打点请求,各浏览器都有不同程度的点击丢失情况,具体点击丢失率统 ...

  4. SQL Server 磁盘请求超时的833错误原因分析以及解决

    本文出处:http://www.cnblogs.com/wy123/p/6984885.html 最近遇到一个SQL Server服务器响应极度缓慢,并且出现客户端请求报错的情况,在数据库中的erro ...

  5. SQL查询速度慢的原因分析和解决方案

    SQL查询速度慢的原因分析和解决方案 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建 ...

  6. PHPWAMP自启异常,服务器重启后Apache等服务不会自动重启的原因分析

    在使用“PHPWAMP自动任务”时,不少学生遇到如下问题: “phpwamp绿色集成环境重启动电脑(服务器)后,不会自动启动网站服务” (如果是其他环境或是自己搭建时遇到此问题,也是可以用此法解决) ...

  7. sql 查询慢的48个原因分析

      sql 查询慢的48个原因分析. server memory 服务器配置选项配置为物理内存的 1.5 倍(虚拟内存大小设置的一半). 字句同时执行,SQL SERVER根据系统的负载情况决定最优的 ...

  8. ORACLE中order by造成分页不正确原因分析

     工作中遇到的问题: 为调用方提供一个分页接口时,调用方一直反应有部分数据取不到,且取到的数据有重复的内容,于是我按以下步骤排查了下错误. 1.检查分页页码生成规则是否正确. 2.检查SQL语句是否正 ...

  9. Android ListView异步载入图片乱序问题,原因分析及解决方式

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android全部系统自带的控件其中,ListView这个控件算是 ...

随机推荐

  1. POJ2104 K-th Number 静态区间第k最值 平方分割

    干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC ...

  2. 启动scala的方法

    1.从官网 http://www.scala-lang.org/download/ 下载scala二进制通用版本以后,在终端命令行添加下载解压包的bin目录到环境变量: export PATH=/Us ...

  3. c++primerplus(第六版)编程题——第3章(数据类型)

    声明:作者为了调试方便,每一章的程序写在一个工程文件中,每一道编程练习题新建一个独立文件,在主函数中调用,我建议同我一样的初学者可以采用这种方式,调试起来会比较方便. 工程命名和文件命名可以命名成易识 ...

  4. .getBoundingClientRect()

    .getBoundingClientRect() 该方法获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置,他返回的是一个对象,即Object,该对象有4个属性:top,left,right, ...

  5. BIOS中断大全

    BIOS中断大全 BIOS中断:1.显示服务(Video Service——INT 10H)  00H —设置显示器模式0CH —写图形象素01H —设置光标形状0DH —读图形象素02H —设置光标 ...

  6. WPF自定义DataGrid分页控件

    新建Custom Control,名:PagingDataGrid 打开工程下面的Themes\Generic.xaml xaml里面代码替换如下 <Style x:Key="{x:T ...

  7. mysql中显示方式的切换

    1. mysql中如果使用\G,则':'不用写.如果\G后面跟':'则会报"error:no query specified"错误.请知晓. 2. mysql在登陆时,mysql ...

  8. yii框架的foreach 已经优化好了,可以“$user_model->attributes=$_POST['Admin'];”

    yii框架的foreach 已经优化好了, 以前我们遍历数组的时候是用foreach循环 foreach ( as $key=>$value){                    $user ...

  9. C#中静态方法和非静态方法的区别(一)

    实例方法比静态方法多传递一个隐含的指针参数,该指针指向该方法所从属的已被实例化的对象.这一区别的外在表现为实例方法内可使用this关键字代表所从属的实例对象,而静态方法不可使用this因为静态方法不针 ...

  10. python自动开发之第十三天

    1.Paramiko模块下的demo.py程序     前面利用Python中的Paramiko模块可以进行SSH的连接,以及用来传送文件(SFTP),但是无论是哪一种方式,连接都是短暂的,并非是长连 ...