HashMap 要点详细记录

HashMap存储结构包含数组、链表和红黑树,适用于JDK1.8。HashMap使用Node存储键值对,当链表长度达到7时转换为红黑树。put方法根据key计算hash插入,超过阈值时会扩容。HashMap线程不安全,可能导致死循环。CurrentHashMap为线程安全的替代,使用分段锁和CAS保证并发安全。

HashMap基础

  • HashMap存储结构为数组、链表、红黑树(JDK1.8)。
  • HashMap由节点Node<K,V>组成。
  • HashMap只允许一个key为null和“”,且若为null,hash值会被赋为0,若为“”空字符串,hash值本来就是0。
  • 若数组某个节点上的Node>=7,则会将链表进化为红黑树,反之若节点<6则会由红黑树退化为链表。
  • HashMap线程不安全,ConcurrentHashMap线程安全。
  • 数组初始化长度为16, Load factor负载因子默认值为0.75,不建议修改,除非有特殊情况。
  • threshold:HashMap所能容纳的最大数据量的Node(键值对)个数。threshold = length * Load factor。最大数量=数组长度*负载因子。
  • HashMap中数组的长度必须为2的幂。

hash方法

  • 此方法作用是确定元素在数组的位置下标,需尽量让元素均匀分布,降低时间复杂度减少碰撞,提高hash方法的离散性能,优化查询效率。
  • hash方法实现分为3步:
    ① 取Node的key的hashCode值。
    ② hashCode与自己的高16位进行异或运算。
    ③ 拿异或的值对数组长度取余,最终得到下标。
  • 哈希运算是一类算法也叫摘要算法,是一种单向散列函数(MD5、SM3等)。作用是输入任意值,通过散列算法固定长度输出。且相同的输入则输出相同,不同的输入大概率输出也不同。所以可以用来检查数据的完整性,保证数据未被篡改。
  • JDK1.8将Key的hash值与自身的高16位进行异或运算,目的是可以在数组table的length比较小的时候让高位也参与运算。
  • 当length是2的n次方时,h& (length-1)运算等价于对length取余,&比%效率更高。(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

put方法

  • HashMap采用懒加载,实例化时不会有初始容量信息。所以put第一步判断length是否为0或table是否为null。
    • 为null,则通过扩容来初始化容量。
  • 根据key计算hash得到插入的数组索引值i。
  • 判断 table[i] == null
    • 为null则插入即可。
  • 若不为null,则判断key是否存在,存在则覆盖。
  • 若不存在则判断table[i] 是否为treeNode。
    • 是红黑树则直接插入键值对 。
  • 若否则开始遍历链表插入。
  • 遍历过程中判断链表长度是否>=7
    • 是则转化为红黑树。
    • 否 则还是链表插入即可。
    • 遍历过程中若发现key存在则直接覆盖。
  • 插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值