HashMap,经典永不过时,不一样的视角和面试技巧

1 核心知识点

  • 底层数据存储结构
  • 初始化容量
  • 扩容机制
  • 线程安全
  • 时间复杂度

2 关键代码分析

  • 底层数据结构

敲黑板:数组+链表+红黑树

先了解底层的数据存储结构,在HashMap内部有table属性

transient Node<K,V>[] table;

可以看到table属性是一个Node数组,那么这个Node又是怎么样一个对象呢

static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

Nodd是HashMap里面的一个静态内部类,里面有四个属性

hash:用来记录key的哈希值

key:记录存储元素的key

value:记录存储元素的value值

next:应用于链表数据结构,当元素数量增加的时候,如果一直保持数组结构,会影响HashMap的存储效率,所以这个元素链表结构需要记录的下一个元素的指针

  • put方法详解
public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

这里关注一下hash(key)这个计算key的hash值的方法

 static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
  1. 判断key是不是为null,如果为null,key的hash值为0,这里说明HashMap的key是可以为null的,。
  2. 如果不为0,则用key的hash值和key值的右移16位的结果进行^计算。这里的原理是,hash值是存在一定概率的冲突的,而我们在计算元素在Node数组中的存储索引的时候,是通过i = (n - 1) & hash这个方式计算,这里的n就是数组的容量大小,n一般不会超过2的16次方65536,也就是1<<<16的结果,所以 (n - 1) & hash进行&计算的时候,高16位是没有参与计算的,为了降低hash冲突,于是把高16位也作为变量因子参与hash值的计算,即h = key.hashCode()) ^ (h >>> 16)。

看看关键方法putVal

fi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慢德

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值