hashMap的put原理

HashMap的put过程详解

HashMap结构


HashMap是一个数组+链表构成的哈希表结构,支持多种数据结构,key和value都可以为null,但是key只能有一个为null;key和value都不可以存放基本数据类型,可以存放他们的封装类;key可以是任意对象,需要重写hashcode方法。
hashmap的put过程:
1.计算key的hashcode值(hashcode是object基类的方法,如果是String类型,他已经重写了hashcode方法,所以保证了同样的值,hashcode值相等;如果是其他类型,需要自己重写hashcode方法,因为,object的hashcode方法只是返回对象的内存地址,相同值的对象,由于在堆中存放的位置不同,hashcode也不同,这就违反了hashmap的key唯一性的定义),
2.根据hashcode计算key的hash值。(使用hash散列算法,目前采用的是:key==null?0:(h=key.hashCode())^(h>>>16);)
3.根据hash值计算数组index。(Entry[]数组的长度在初始化的时候会被指定,index需要尽可能的分布均匀;两种算法:取模运算(index=hash%length)和位运算(index=hash&(length-1);但是位运算有个前置条件:length的值必须是2的n次幂,因为只有这样,hash%length=hash&(length-1)才成立,实践证明,这样可以降低hash碰撞,就减少存放在链表的可能性,相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。 );两者都能保证key分布在Entry[0,length-1]上,但是取模运算效率低,所以选用位运算进行映射。)
得到index之后,判断Entry[index]当前数组位置上是否已经有值,如果没有,直接插入;如果有值,需要根据equals方法判断key是否已经存在,存在的话直接覆盖;不存在的话,判断Entry[index]是否是treeNode,是的话直接红黑树插入value;如果不是的话,开始遍历链表准备插入,插入后判断此时链表长度是否大于8,大于的话转换为红黑树,插入,不大于的话,根据equals方法判断key是否已经存在,存在的话直接覆盖,不存在的话,直接插入到最前面,其他value后移。
插入之后判断此时size是否大于阈值,大于的话需要resize进行扩容,重新映射。

总结:

1.底层存储数据的数组,在第一次put元素的时候初始化,同时发生第一次扩容;

2.相比较JDK 1.8之前的版本,JDK 1.8在链表长度大于8的时候,会转化为红黑树处理,主要是基于效率的考量;

发布了23 篇原创文章 · 获赞 0 · 访问量 2937

猜你喜欢

转载自blog.csdn.net/kris_lh123/article/details/102841924
今日推荐