【零基础学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;

相关推荐
程序员清风21 小时前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5511 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊1 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing1 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠2 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840822 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide2 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家2 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺2 天前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户908324602732 天前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端