【零基础学java】(HashMap源码解析--添加第一个元素)

前言:

Map集合的底层原理,源码解析

Cltr+F12 搜索

Cltr+B跟进

Cltr+Alt+左键,回到上一步

向上的箭头,表示该方法是重写后的

向后的箭头,表示该方法是来自哪个类或者哪个接口

解释:

HashMap
哈希值只跟键有关系,跟值没有一点关系
Node<K,V>[]table 哈希表结构中数组的名字
DEFAULT---INITIAL---CAPACITY 默认数组长度16
DEFAULT---LOAD---FACTOR默认加载因子为0.75

HashMap里面的每一个对象包含以下内容

链表中的键值对对象

包含:int hash //键的哈希值

finalK key //键

v value //值

Node<K,V>nex t //下一个节点的地址值

红黑树中的键值对对象

包含:int hash //键的哈希值

finalK key //键

v value //值

TreeNode<K,V>parent //父节点的地址值

TreeNode<K,V>left //左子节点的地址值

TreeNode<K,V>right//右子节点的地址值

boolean red 节点的颜色

数组里面的键值对对象需要分情况讨论

1.创建对象

HashMap<String,Integer> hm = new HashMap<>();

2.添加元素

hm.put("aaa" , 111);

hm.put("bbb" , 222);

hm.put("ccc" , 333);

hm.put("ddd" , 444);

hm.put("eee" , 555);

添加元素的时候至少考虑三种情况:
2.1数组位置为null
2.2数组位置不为null,键不重复,挂在下面形成链表或者红黑树
2.3数组位置不为null,键重复,元素覆盖

put方法的底层源码(添加第一个元素时)

参数一:键

参数二:值

返回值:被覆盖元素的值,如果没有覆盖,返回null

public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}

第一个参数hash(key),利用键计算出对应的哈希值,再把哈希值进行一系列的额外处理

简单理解

//参数一:键的哈希值

//参数二:键

//参数三:值

//参数四:如果键重复了是否保留

true表示老元素的值保留,不会覆盖

false,表示老元素的值不保留,会进行覆盖

//参数五暂时不了解

static final int hash(Object key) {

int h;

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {

//定义一个局部变量,用来记录哈希表中数组的地址值。

Node<K,V>[] tab;

//临时的第三方变量,用来记录键值对对象的地址值

Node<K,V> p;

//表示当前数组的长度

int n;

//表示索引

int i;

//把哈希表中数组的地址值,赋值给局部变量tab

tab = table;

if (tab == null || (n = tab.length) == 0){

//1.如果当前是第一次添加数据,底层会创建一个默认长度为16,加载因子为0.75的数组
//2.如果不是第一次添加数据,会看数组中的元素是否达到了扩容的条件
//如果没有达到扩容条件,底层不会做任何操作
//如果达到了扩容条件,底层会把数组扩容为原先的两倍,并把数据全部转移到新的哈希表中

tab = resize();

//表示把当前数组的长度赋值给n

n = tab.length;

}

//拿着数组的长度跟键的哈希值进行计算,计算出当前键值对对象,在数组中应存入的位置

i = (n - 1) & hash;//index

//获取数组中对应元素的数据

p = tab[i];

if (p == null){

//底层会创建一个键值对对象,直接放到数组当中(第一个元素)

tab[i] = newNode(hash, key, value, null);

//threshold:记录的就是数组的长度 * 0.75,哈希表的扩容时机 16 * 0.75 = 12

if (++size > threshold){

resize();

}

//表示当前没有覆盖任何元素,返回null

return null;

相关推荐
张柏慈14 小时前
Java性能优化:实战技巧与案例解析
java
天“码”行空14 小时前
简化Lambda——方法引用
java·开发语言
带刺的坐椅15 小时前
MCP 进化:让静态 Tool 进化为具备“上下文感知”的远程 Skills
java·ai·llm·agent·solon·mcp·tool-call·skills
java1234_小锋15 小时前
Java线程之间是如何通信的?
java·开发语言
张张努力变强15 小时前
C++ Date日期类的设计与实现全解析
java·开发语言·c++·算法
while(1){yan}16 小时前
Spring事务
java·数据库·spring boot·后端·java-ee·mybatis
毕设源码-赖学姐16 小时前
【开题答辩全过程】以 高校社团管理平台为例,包含答辩的问题和答案
java
余瑜鱼鱼鱼17 小时前
线程和进程的区别和联系
java·开发语言·jvm
小唐同学爱学习17 小时前
如何解决海量数据存储
java·数据库·spring boot·mysql
962464i17 小时前
SBE(simple-binary-encoding)-Demo
java