HashMap底层原理

HashMap在JDK 1.8之前的版本采用数组+链表的数据结构,1.8及以后增加了红黑树。其核心是通过哈希算法确定key在数组中的位置,解决碰撞。HashMap在节点数量达到特定阈值时进行扩容,1.7版本的扩容可能导致多线程下的死循环问题,1.8版本通过改进扩容策略解决了这一问题,并引入了红黑树以提高检索效率。
摘要由CSDN通过智能技术生成

在 JDK 1.8 版本之前,HashMap 底层的数据结构是数组 + 链表,如下图:

在 1.8 及以后是数组 + 链表 + 红黑树

重要的几个变量

  • DEFAULT_INITIAL_CAPACITY = 1 << 4; Hash 表默认初始容量
  • MAXIMUM_CAPACITY = 1 << 30; 最大 Hash 表容量
  • DEFAULT_LOAD_FACTOR = 0.75f;默认加载因子
  • TREEIFY_THRESHOLD = 8;链表转红黑树阈值
  • UNTREEIFY_THRESHOLD = 6;红黑树转链表阈值
  • MIN_TREEIFY_CAPACITY = 64;链表转红黑树时 hash 表最小容量阈值,达不到优先扩容

存放数据

Map <String,Employee> map = new HashMap <> ();
Employee e0 = new Employee("zhangshan");
map.put("zhangshan", e0);

会对 “zhangshan” 进行一次 hash 运算, 把 “zhangshan” 这个字符串映射成一个小于数组长度的整型值。就像下面这样:

int i = hash("zhangshan") 假如 i 等于 1,就会把 e0 构造成一个节点,放入数组下标为 1 的位置。数组存放的是一个节点,该节点有指向下一个节点的指针 next, 如下:

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

int i = hash("zhangshan") 把字符串映射成一个整型,不同的字符串可能映射成相同的位置,有下面这种可能:

hash("zhangshan") == hash("lisi")

这就是 hash 碰撞,出现碰撞后,会以链表的方式追加在后面,就形成了上图中的结构。

如何确定 key 在数组中的位置

先看 jdk 1.7 中的实现:

public V put(K key, V value) {
     
    if (table == EMPTY_TABLE) {
     
        inflateTable(threshold);  
    }  
    if (key == null)  
        return putForNullKey(value);  
    //  获取 key 对应的整型 hash值
    int hash = hash(key);  
    // 再将这个hash值转换为小于这个数组的整型值 i,然后将节点插入数组i位置
    int i = indexFor(hash, table.length);  
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
     
        Object k;  
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
     
            V oldValue = e.value;  
            e.value = value;  
            e.recordAccess(this);  
            return oldValue;  
        }  
    }  
  
    modCount++;  
    addEntry(hash, key, value, i);  
    return null;}

其中 hash 方法如下:

final int hash(Object k) {
     
    int h = hashSeed;  
    if (0 != h && k instanceof String) {
     
        return sun.misc.Hashing.stringHash32((String) k);  
    }  
  
    h ^= k.hashCode
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值