HashMap保存键值对步骤

HashMap实现结构

JDK1.7中,HashMap数据结构为数组+链表
JDK1.8之后增加了数组+链表+红黑树变换

存放元素的逻辑

HashMap存储的键值对Key-Value,Key具有唯一性,采用了链地址法来处理哈希冲突,当往 HashMap 中添加元素时,会计算 key 的 hash 值取余得出元素在数组中的的存放位置。

一、HashMap的一些参数

//第一次添加元素时,初始化长度为16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//最大长度
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认装载因子0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//是否将链表转换为树的临界值
static final int TREEIFY_THRESHOLD = 8;
//是否将树转换为链表的临届值
static final int UNTREEIFY_THRESHOLD = 6;
//当链表长度大于8并且数组长度大于64时,链表转换为树
static final int MIN_TREEIFY_CAPACITY = 64;
//HashMap的长度
transient int size;
//扩容阈值
int threshold;
//装载因子
final float loadFactor;
//底层存放k-v的数组
transient Node<K,V>[] table;
//保存缓存的entrySet()
transient Set<Map.Entry<K,V>> entrySet; 

二、HashMap的构造函数

1 public HashMap(int initialCapacity, float loadFactor)

有参构造
初始化装填因子和扩容阈值

在这里插入图片描述
2 public HashMap(int initialCapacity)

有参构造
初始化扩容阈值
装填因子默认0.75

public HashMap(int initialCapacity) {
	this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

3 HashMap()

无参构造
仅将装载因子设置为默认值0.75

public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // 0.75
}

4 HashMap(Map<? extends K, ? extends V> m)

将Map实例对象作为参数,初始化HashMap,将Map内元素给HashMap
将装载因子设置为默认值0.75

public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        putMapEntries(m, false);
}

进入putMapEntries(m, false)

1.如果m的为空,什么都不做
2.如果m不为空,如果HashMap为空,对其进行初始化

扩容阈值 threshold=m.size()*装填因子(0.75)

3.如果HashMap不为空,并且m.size>扩容阈值,对其进行扩容
4.将m中键值对逐个放入Map中

putMapEntries

三、HashMap存放元素的过程

1 进入put(K key, V value)方法

直接返回putVal(hash(key), key, value, false, true)

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}

2 进入putVal(hash(key), key, value, false, true)

参数:

hash(key) : hashcode的高16位------不容易产生冲突
key : 键
value : 值

  1. 第一次添加元素时,要进行一次resize()扩容,n=扩容后的长度
  2. 通过散列函数计算数据要存放的位置,若该位置为空则直接往里添加

在这里插入图片描述

如果通过散列函数计算出的下标位置有元素:

  1. 通过hash、key地址和key内容判断是要存放的元素和该位置的元素是否为同一个元素,若为同一个元素,则覆盖
  2. 若不是同一个元素,即产生了冲突,使用链地址法解决冲突,如果p是红黑树的结点,则存放到红黑树中
  3. 若不是树的结点,如果是p时Node结点,采用尾插法将元素插入

如果链表长度大于等于8,而且哈希表长度小于64,则扩容哈希表,否则将链表转化为红黑树
如果链表中已经存在要插入的元素,则不再进行插入

在这里插入图片描述

如果e不为null,说明map中已经存在所要添加到key,如果value不同,返回旧value,

在这里插入图片描述

前部分只有一个key存在,覆盖value里有return跳出方法,到此处说明key作为一个新元素已经添加进了HashMap中,如果此时元素个数>扩容阈值,则需要resize()进行扩容,返回null

在这里插入图片描述
3 resize

初始化或加倍表的大小。如果为空,则根据当前阈值中保持的初始容量目标进行分配。如果不为空,则进行2倍扩容,返回:扩容后的table

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值