HashMap底层原理详解:扩容、红黑树与ConcurrentHashMap的线程安全

HashMap作为Java集合框架中最重要且最常用的数据结构之一,其底层实现原理和线程安全方案是Java开发者必须掌握的核心知识。本文将深入剖析HashMap的实现机制,并详细解释ConcurrentHashMap如何保证线程安全。

一、HashMap底层数据结构

1.1 数组+链表+红黑树结构

HashMap在JDK 1.8后的底层实现采用"数组+链表+红黑树"的混合结构:

java

// HashMap中的核心数组定义
transient Node<K,V>[] table;

// 链表节点定义
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
    // ...
}

// 红黑树节点定义
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // 红黑树链接
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // 删除后需要取消链接
    boolean red;
    // ...
}

1.2 哈希计算与索引定位

HashMap通过哈希函数确定键值对的存储位置:

java

// 计算key的哈希值
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

// 计算数组下标
int index = (table.length - 1) & hash(key);

高16位与低16位异或运算的目的是为了增加哈希值的随机性,减少哈希冲突。

二、HashMap扩容机制

2.1 扩容触发条件

HashMap在以下情况下会触发扩容:

  1. 初始化后首次插入元素:默认创建长度为16的数组

  2. 元素数量超过阈值:阈值 = 容量 × 负载因子(默认0.75)

  3. 链表长度达到8但数组长度小于64:优先扩容而不是树化

2.2 扩容过程

扩容过程主要分为以下步骤:

java

final Node<K,V>[] resize() {
    // 1. 计算新容量和新阈值
    int newCap = oldCap << 1;  // 双倍扩容
    float newThr = oldThr << 1;
    
    // 2. 创建新数组
    Node<K,V>[] ne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值