HashMap总结

概述

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

API

put

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

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

get

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

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

知识点

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

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

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

  • HashMap是线程安全的吗?

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

  1. Capacity:HashMap的当前长度。HashMap的长度是2的幂
  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或者value
  • HashMap的index =  HashCode(Key) &  (Length - 1),HashTable的index = (hash & 0x7FFFFFFF) % tab.length
  • HashMap的初始化容量大小和扩容后大小总是2的幂,HashTable初始化容量大小是11,扩容后大小为老容量的二倍加一
  • HashMap和HashTable都实现了Map接口,但是HashTable继承了Dictionary,HashMap继承了AbstractMap

参考程序员小灰的公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值