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

相关推荐
向上的车轮7 小时前
为什么.NET(C#)转 Java 开发时常常在“吐槽”Java:checked exception
java·c#·.net
Dragon Wu7 小时前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
跳动的梦想家h7 小时前
环境配置 + AI 提效双管齐下
java·vue.js·spring
坚持就完事了7 小时前
Java中的集合
java·开发语言
wjhx7 小时前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
YCY^v^7 小时前
JeecgBoot 项目运行指南
java·学习
人间打气筒(Ada)8 小时前
jenkins基于Pipeline发布项目
java·pipeline·jenkins·流水线·ci·cd·cicd
爬山算法8 小时前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
自不量力的A同学8 小时前
Solon AI v3.9 正式发布:全能 Skill 爆发
java·网络·人工智能
万岳科技系统开发8 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法