HashMap源码深度解读

本文详细解读了HashMap在JDK7和JDK8中的实现原理,包括其数据结构、put和get方法的实现。特别讨论了JDK8中为解决hash冲突引入的红黑树,以及HashMap的线程安全性问题和潜在问题。
摘要由CSDN通过智能技术生成

HashMap解读

在面试的过程中,面试官经常会向面试者提问关于HashMap的问题,今天我将在这篇文章中仔细介绍一下HashMap.

jdk7中的HashMap

介绍一下HashMap及其put和set方法实现

HashMap是由数组加上链表的数据结构书写的,它使用key-value键值对形式存储数据,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。
初始化结构

下面是几个比较重要的参数

//数组的默认长度,16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//默认的加载因子0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//数组的最大长度 2的30次方(1073741824)
static final int MAXIMUM_CAPACITY = 1 << 30;
static final Entry[] EMPTY_TABLE = {};
//table'用来存放数据的位置
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
// 存放的键值对的数量大小,Entry的数量
transient int size; 
//桶(bucket)的大小,可在初始化时显式指定
int threshold;
//加载因子,可在初始化时显式指定。
final float loadFactor;
//修改的次数,用于fail-fast机制
transient int modCount;

这个数组的默认长度为16,默认加载因子为0.75,数组里面的每一个值初始化的时候默认为null.当桶中总的键值对(Entry)的数量达到capacity * loadFactor的大小时,数组就会扩容,第一次扩容发生在数组中Entry数量为16*0.75f=12时.每次扩容都会使得数组的容量变为原来的两倍.这两个参数在创建HashMap对象的时候都可以指定,但我们一般不指定.

对于HashMap我们最常用的两个方法就是putget

put

jdk7中的源码如下

    public V put(K key, V value) {
    //如果此时的table仍旧为初始化时的EMPTY_TABLE(空数组)的话,就对其进行初始化扩容
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
    //如果想要存放的数据的key值为空的话,那么就调用putForNullKey方法.
    //putForNullKey会覆盖掉原先的null值对应的Entry的value(如果存在的话)
        if (key == null)
            return putForNullKey(value);
    //对于非空的key存取方法如下
    //1.计算hash值
        int hash = hash(key);
    //2.计算该hash值在table中的位置
        int i = indexFor(hash, table.length);
    //3.判断此位置中是否有Entry存在,使用equals方法判断新插入的键是否等于原有的键, 
    //相同的话就覆盖原有Entry的值,不同的话就插入链表的最上方
    //并使新插入Entry指向原先的Entry
        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++;
        //如果前面return的话,也就不会来到这里调用addEntry方法了
        addEntry(hash, key, value, i);
        return null;
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值