HashMap(JDK7)在多线程下形成环形链表的原因

本文详细介绍了Java HashMap的内部结构,包括其数组+链表的存储方式,以及初始化、添加元素、扩容和转移元素的过程。特别地,文章通过示例代码解释了在多线程环境下,HashMap扩容可能导致的环形链表问题,分析了其原因在于头插法扩容导致的链表顺序反转。

一、HashMap结构

大家都知道在JDK7中HashMap是用数组+链表的方式存储元素的。

二、初始化

HashMap的构造器有4个,其中三个是以容量(initialCapacity,容量是用来计算数组table的大小的)和负载因子(loadFactor)为参数,另外一个构造器是以Map为参数。无参构造器调用的是参数为容量和负载因子的构造器,默认容量为16,负载因子为0.75f。默认的阈值(threshold)为容量大小。

public HashMap() {
   
   
    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
public HashMap(int initialCapacity) {
   
   
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public HashMap(int initialCapacity, float loadFactor) {
   
   
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " +
                                           initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                                           loadFactor);

    this.loadFactor = loadFactor;
    threshold = initialCapacity;
    init();
}

三、添加元素

当没有元素的时候,会先根据threshold对其膨胀(inflateTable),膨胀的作用就是新建一个长度适当的数组。数组的长度计算逻辑是:如果参数值toSize大于等于最大容量2的30次方,则长度为2的30次方,否则返回大于或等于toSize的最小的2的N次方的数。例如,toSzie是7,则长度就会为8,刚好是2的3次方。

public V put(K key, V value) {
   
   
    if (table == EMPTY_TABLE) {
   
   
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值