lesson10:hashmap变慢原因分析
下面的英文描述了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变慢原因分析的更多相关文章
- SELECT TOP 1 比不加TOP 1 慢的原因分析以及SELECT TOP 1语句执行计划预估原理
本文出处:http://www.cnblogs.com/wy123/p/6082338.html 现实中遇到过到这么一种情况: 在某些特殊场景下:进行查询的时候,加了TOP 1比不加TOP 1要慢(而 ...
- HashMap多线程并发问题分析
转载: HashMap多线程并发问题分析 并发问题的症状 多线程put后可能导致get死循环 从前我们的Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题. ...
- Beforeunload打点丢失原因分析及解决方案
淘宝的鱼相在 2012 年 8 月份发表了一篇文章,里面讲述了他们通过一个月的数据采集试验,得到的结果是:如果在浏览器的本页面刷新之前发送打点请求,各浏览器都有不同程度的点击丢失情况,具体点击丢失率统 ...
- SQL Server 磁盘请求超时的833错误原因分析以及解决
本文出处:http://www.cnblogs.com/wy123/p/6984885.html 最近遇到一个SQL Server服务器响应极度缓慢,并且出现客户端请求报错的情况,在数据库中的erro ...
- SQL查询速度慢的原因分析和解决方案
SQL查询速度慢的原因分析和解决方案 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建 ...
- PHPWAMP自启异常,服务器重启后Apache等服务不会自动重启的原因分析
在使用“PHPWAMP自动任务”时,不少学生遇到如下问题: “phpwamp绿色集成环境重启动电脑(服务器)后,不会自动启动网站服务” (如果是其他环境或是自己搭建时遇到此问题,也是可以用此法解决) ...
- sql 查询慢的48个原因分析
sql 查询慢的48个原因分析. server memory 服务器配置选项配置为物理内存的 1.5 倍(虚拟内存大小设置的一半). 字句同时执行,SQL SERVER根据系统的负载情况决定最优的 ...
- ORACLE中order by造成分页不正确原因分析
工作中遇到的问题: 为调用方提供一个分页接口时,调用方一直反应有部分数据取不到,且取到的数据有重复的内容,于是我按以下步骤排查了下错误. 1.检查分页页码生成规则是否正确. 2.检查SQL语句是否正 ...
- Android ListView异步载入图片乱序问题,原因分析及解决方式
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/45586553 在Android全部系统自带的控件其中,ListView这个控件算是 ...
随机推荐
- Vijos1865 NOI2014 魔法森林 LCT维护生成树
基本思路: 首先按照weightA升序排序,然后依次在图中加边,并维护起点到终点路径上weightB的最大值 如果加边过程中生成了环,则删除环中weightB最大的边 由于是无向图,点之间没有拓扑序, ...
- 服务器上搭建spark开发环境
1.安装相应的软件 (1)安装jdk 下载地址:http://www.Oracle.com/technetwork/java/javase/downloads/index.html (2)安装scal ...
- 关键字throw(something)限制
C++函数后加关键字throw(something)限制,是对这个函数的异常安全性作出限制.void f() throw() 表示f不允许抛出任何异常,即f是异常安全的.void f() throw( ...
- call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.
call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 注意:该函数的语法与 apply() 方法的语法几乎完全相同,唯一的区别在于,apply()方法接受的是一个参 ...
- JS 返回上一步(退回上一步上一个网页)
链接式: <a href="JavaScript:history.go(-1)">返回上一步</a> <a href="<%=Requ ...
- srand((double)microtime()*1000000)
分为4个步骤1:执行microtime(),获取当前的微秒数 2:把获取的微秒数转换为double类型 3:再用转换后的数字去乘以1000000 4:给随机数发生器播种,播种数为第三步得出的结果 ra ...
- Day8 面向对象(补充)
私有字段 class Foo: def __init__(self, name): self.__name = name def f1(self): print(self.__name) class ...
- shell排序算法
今天看<The C Programming Language>的时候看到了shell排序算法, /* shellsort: sort v[0]...v[n-1] into increasi ...
- SSH三种框架及表示层、业务层和持久层的理解
Struts(表示层)+Spring(业务层)+Hibernate(持久层) SSH:Struts(表示层)+Spring(业务层)+Hibernate(持久层) Struts:Struts是一个表示 ...
- MySQL 执行计划explain详解
MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...