HashMap超全源码详解(JDK1.8)

1、HashMap简介

HashMap基于哈希表的Map接口实现,是以key-value存储形式存在。JDK1.8版本中其数据结构是:数组+链表+红黑树的形式。下面详解源码及解决的问题。

2、HashMap类

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable 

接口方法:

  • put方法(新增 )
  • resize方法(扩容 )
  • get方法(遍历)
  • remove方法(删除)
  • treeifyBin方法(链表树化)
  • untreeify方法(红黑树转链)

成员变量:

  • table变量:HashMap的底层是Node类的实体数组,Node是一个静态内部类,一种数组和链表相结合的复合结构,用于保存key-value对;
  • size变量:表示已存储的HashMap的key-value对的数量;
  • loadFactor变量:装载因子,默认值为0.75f(DEFAULT_LOAD_FACTOR = 0.75f;);
  • threshold变量:临界值,超过此值hashmap自动扩容,threshold=容量*加载因子;
  • capacity:容量,非成员变量,默认值是16;

3、HashMap方法详解

1.put方法源码及总结

总结:

  • 判断HashMap中的数组是否为空或者大小为0,如果是则初始化数组。
  • 如果该hash值对应的数组中的位置为空,则将该数据组成的节点直接插入到该位置中。
  • 如果数组对应位置数据不为空,判断该位置节点的key与要插入的key是否相等,如果是设置e(局部变量)等于该节点。
  • 如果Node结构为树结构,则遍历树结构找到key对应的节点,设置为e。
  • 如果Node结构为链表,遍历链表,如果链表中没有找到对应的key,将数据构造成Node节点插入链表最后,如果链表长度大于等于8,则将结构转为树。
  • 如果在链表中找到对应的key,则将该节点设置为e.
  • 如果e(上面遍历找到的节点)不为null,则设置新的value,返回旧的value.
  • 如果e为null,说明是新增,HashMap大小加一,判断是否大于阈值,如果大于,则扩容。

2.get方法源码及总结

总结:

  • 根据key的hash值找到数组中对应的位置。
  • 判断该位置上的值和要查找的值是否相等(==或者equals),如果是则返回
  • 如果不是则判断该节点的下一个节点是否为空,为空则返回null。
  • 判断结构是否是红黑树,如果是,遍历树。
  • 如果不是树,则遍历链表。
  • 如果不符合上面的条件则返回null。

3.resize(扩容)方法源码及总结

总结:

  • 数组是否已经达到最大值,如果已经最大,设置阈值也为最大值,否则数组大小和阈值都改为之前的两倍。
  • 数组是否已经初始化,如果没有则初始化数组和阈值。
  • 旧数组不为null,遍历旧数组,将对应位置的链表/树分为成两个链表/数组,一个在原先的位置上,一个在原先的位置+原先数组大小的位置上,将两个链表/树放入新数组的对应位置。

jdk1.8的优化

由JDK1.7的,数组 + 链表

JDK1.8变为:数组 + 链表 + 红黑树

具体触发条件为:某个链表连接的个数大于8,并且总的容量大于64的时候,那么会把原来的链表转换成红黑树。这么做的好处是什么:红黑树除了添加元素外,查询和删除效率比链表快。

红黑树查询、增加和删除的时间复杂度:O(log2n)

链表的查询和删除的时间复杂度: O(n),插入为:O(1)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值