Hashmap简介

Posted 麦克叔叔每晚10点说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hashmap简介相关的知识,希望对你有一定的参考价值。

HashMap

java为啥会出现map?map有啥用? 或者更直接的,java为啥用k,v键值对形式存储数据? 


答案出奇的简单,就是为了快速查找,删除。基于这两点,map就应运而生了。不管是treeMap,还是hashMap都是通过一些算法实现了快速的查找删除。这里我们主要讲下hashMap(treeMap底层是红黑树算法,这里不作讨论)。


这里多提一句,所有的算法都是为性能优化提供的解决方案,所以以后我会收集一些常用算法分享给大家。大家自己有兴趣可以先了解以下几种比较常用的简单的算法:


二叉树中的红黑树、b树、b+树、一致性hash,这四个算法分别用于java中的treemap、系统文件查找、数据库索引、分布式缓存,当然,其它的更简单的算法,比如一些排序算法就不做多的介绍了。


hashMap底层原理就是hash算法,java提供了重写hashCode方法来重新hash,不过这会造成hash不好的话会导致hashMap性能直线下降,一般不建议重写。


hashMap比较重要的一个概念就是加载因子(loadFactor,默认0.75),加载因子的出现是一种性能妥协,就是空间换时间,因为当经过hash算出来hashCode值后,会先在数组里面去找到这个位置,然后看是否存有数据了,如已经数据了,然后再获取遍历链表做插入或者替换操作,这个比没找到直接放入value是慢很多的,特别是当map空间差不多满了的时候,会做很多查找比较替换,所以在设计hashMap的时候有意不让map是全满状态,每次只装initSize*loadFactor这么多个,超出就扩容,这样就可以降低查找比较替换时间,让hashMap性能最优。


    也有人将上面的过程简单概括为hash碰撞,为了更清楚的说明,就写得比较啰嗦了,对hash碰撞已经知道的就不必详细读上面大段内容了。

hashMap

原理图

   

存流程:hash(key)得到存储index,然后table[index]得到entry链表,遍历链表并且equals(key),存在就替换value,不存在就新增链表节点。这里注意下,在存的时候当useSize(当前占用的size)>=initSize*loadFactor时,会扩展hashMap可用空间(前面已提到这里再强调下)。


取流程:与存流程唯一不一致的就是后面的equals(key)是返回找到的值而已。

Hashmap简介

  代码实现

Hashmap简介
Hashmap简介

Person类

Hashmap简介
Hashmap简介

测试

Hashmap简介
Hashmap简介

运行结果

Hashmap简介
Hashmap简介
Hashmap简介

当把equals方法注释掉后运行结果

Hashmap简介

下面再来验证下当hashCode值相同时,不同对象存储的位置相同,以及当hashMap空间不够时,hashMap扩容所占用的时间

 

Hashmap简介

  1.测试hashcode相同,不扩容存储耗时

Hashmap简介

代码:

     注释掉person的equals方法

Hashmap简介

测试

Hashmap简介
Hashmap简介

结果

Hashmap简介
Hashmap简介

  2.测试hashcode不相同,不扩容存储耗时

Hashmap简介
Hashmap简介
Hashmap简介

可以明显看出,当其它条件不变,存储在同一位置和存储在不同位置所占用的时间相差是巨大的。这里我也测试了下扩容的时候的比较以及装载因子的影响,发现相同条件下,重新hash的时间相差是很小的,所以由此可见,hashMap对性能影响最大的还是hash散列得是否均匀,即是否在同一位置存储的数据过多。


这里我为了测试比较客观,所以用了1000个线程跑平均值,但是因为hashMap不是线程安全的,所以在put的时候数据量不宜过大,不然hashMap会被挂起而看不到测试结果。


解决方案请参看

http://www.cnblogs.com/andy-zhou/p/5402984.html



Hashmap简介

麦克叔叔每晚十点说


以上是关于Hashmap简介的主要内容,如果未能解决你的问题,请参考以下文章

Hashmap简介

HashMap源码分析

HashMap底层源码解析上(超详细图解+面试题)

HashMap详解(基于JDK 1.8)

深入理解HashMap和TreeMap的区别

HashMap简介以及hashCode写法的建议