HashMap底层源码剖析

本文深入剖析HashMap的底层实现,包括数组+链表+红黑树的数据结构,hash碰撞解决策略,红黑树的选择原因及临界值8的设定,put()和get()操作的底层逻辑,以及HashMap的扩容机制。通过理解这些,能更好地掌握HashMap的高效性和性能优化。
摘要由CSDN通过智能技术生成

一、HashMap底层用到的数据结构

数组+单向链表+红黑树

  数组:数组每一项都是一个链表,其实就是数组和链表的结合体

  单向链表:当法神hash碰撞时,首先会找到数组对应位置,然后1.8采用尾插入法(1.7采用头插入法),形成一个单项链表结构

  JDK1.8 红黑树:当数组中每项的链表长度大于8时,会转换为红黑树

二、什么是hash碰撞?解决方案?

  hash碰撞:不同的key可能会产生相同的hash值;

  方案:链表发,再哈希法;

  hashMap中采用链表发,在ConcurrentHashMap中采用哈希法;

二、红黑树与二叉树比较

  二叉查找树在特殊情况下也会变成线性结构,和原来链表有共同的问题,节点太深,查找性能慢;

  红黑树相比二叉树,在检索的时候效率其实差不多,都是通过平衡来二分查找。但对于插入删除等操效率提高很多。红黑树不像二叉树一样追求绝对的平衡,它允许局部很少的不完全平衡,这样对于效率影响不大,但省去了很多没有必要的调平衡操作,二叉树调平衡有时候代价较大,所以二叉树的效率不如红黑树;

三、为什么采用红黑树

  在平常我们用HashMap的时候,HashMap里面存储的key是具有良好的hash算法的key(比如String、Integer等包装类),冲突几率自然微乎其微,此时链表几乎不会转化为红黑树,但是当key为我们自定义的对象时,我们可能采用了不好的hash算法,使HashMap中key的冲突率极高,但是这时HashMap为了保证高速的查找效率,就引入了红黑树来优化查询了。

四、为什么临界值为8

  通过源码我们得知HashMap源码作者通过泊松分布算出,当桶中结点个数为8时,出现的几率是亿分之6的,因此常见的情况是桶中个数小于8的情况,此时链表的查询性能和红黑树相差不多,因为转化为树还需要时间和空间,所以此时没有转化成树的必要。

  当数据较少的时候,采用链表要比红黑树效率高,因为平衡二叉树保持平衡需要耗费资源,那么前期数据较少时采用链表,当链表中的数据长度大于8时,就将链表转换成红黑树,可以加快数据的插叙速度,官方测试8为性能最优

五、put()底层分析

复制代码

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    /**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        //判断当前数组是否为空,如果为空要进行第一次扩容
        if ((tab = table) == null || (n = tab.length) == 0)
            //扩容后将扩
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值