HashMap总结

    xiaoxiao2022-06-26  145

    概述

    HashMap是一个存储key-value键值对的集合,每个键值对也叫Entry,每个Entry可以看做是一个链表的节点,每个元素的初始值都是null。

    API

    put

    新插入一个key为“dog”的元素,调用hashMap.put("dog",0):

    首先利用哈希函数来确定Entry的插入位置,index=Hash(“dog”)放入指定的位置,若该位置无元素,Entry放入该位置,若该位置有元素,及发生hash冲突,执行3。我们的Entry元素的next指针指向该位置存在的Entry对象,可抽象理解为纵向插入链表中。需要注意的是,新来的Entry对象的对象使用的是头插法,因为发明者认为后插入的Entry被查找的可能性更大。

    get

    查找一个key为“dog”的元素,调用hashMap.get("dog",0):

    get方法根据index=Hash("dog"),找到该位置的索引如果该位置有多个元素Entry,那么顺着对应链表的头结点一个一个找,找到为止。

    知识点

    HashMap的初始长度是多少,为什么这么规定?

    初始长度是16,每次自动拓展或者手动扩展失,长度都必须是2的幂,之所以这样选择是因为key映射到index的Hash算法

    index =  HashCode(Key) &  (Length - 1),Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。2的幂-1的二进制都是111111....,index的结果会更加均衡分布,

    HashMap是线程安全的吗?

    不是线程安全的,在HashMap随着插入元素达到一定的饱和度时,会进行Resize操作,影响Resize的操作有两个:

    Capacity:HashMap的当前长度。HashMap的长度是2的幂LoadFactor:HashMap负载因子,默认值为0.75f。

    衡量HashMap是否进行Resize的条件如下:HashMap.Size   >=  Capacity * LoadFactor

    Resize的两个步骤:

    扩容:创建一个新的Entry数组,长度为原来的二倍。ReHash:遍历原Entry数组,把所有的Entry根剧新的Hash算法重新Hash到新数组。

    HashMap在设计上很完美,不过存在线程安全问题,在Resize达到临界点时,两个线程同时操作可能出现死锁。

    高并发情况下,为什么HashMap可能出现死锁?

    https://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw==&mid=2653192000&idx=1&sn=118cee6d1c67e7b8e4f762af3e61643e&chksm=8c990d9abbee848c739aeaf25893ae4382eca90642f65fc9b8eb76d58d6e7adebe65da03f80d&scene=21#wechat_redirect

    在Java 8中HashMap的结构有怎么样的优化?

    HashMap和HashTable的区别

    HashMap允许存放null key和null value,HashTable不允许存放null的key或者valueHashMap的index =  HashCode(Key) &  (Length - 1),HashTable的index = (hash & 0x7FFFFFFF) % tab.lengthHashMap的初始化容量大小和扩容后大小总是2的幂,HashTable初始化容量大小是11,扩容后大小为老容量的二倍加一HashMap和HashTable都实现了Map接口,但是HashTable继承了Dictionary,HashMap继承了AbstractMap

    参考程序员小灰的公众号


    最新回复(0)