HashMap的put方法讲解
public V put(K key, V value) {// 调用hash(key)计算出key的hash值return putVal(hash(key), key, value, false, true);
}static final int hash(Object key) {int h;// 如果key为null,则hash值为0,否则调用key的hashCode()方法// 并让高16位与整个hash异或,这样做是为了使计算出的hash更分散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, i;// 如果桶的数量为0,则初始化if ((tab = table) == null || (n = tab.length) == 0)// 调用resize()初始化n = (tab = resize()).length;// (n - 1) & hash 计算元素在哪个桶中// 如果这个桶中还没有元素,则把这个元素放在桶中的第一个位置if ((p = tab[i = (n - 1) & hash]) == null)// 新建一个节点放在桶中tab[i] = newNode(hash, key, value, null);else {// 如果桶中已经有元素存在了Node<K, V> e;K k;// 如果桶中第一个元素的key与待插入元素的key相同,保存到e中用于后续修改value值if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)// 如果第一个元素是树节点,则调用树节点的putTreeVal插入元素e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);else {// 遍历这个桶对应的链表,binCount用于存储链表中元素的个数for (int binCount = 0; ; ++binCount) {// 如果链表遍历完了都没有找到相同key的元素,说明该key对应的元素不存在,则在链表最后插入一个新节点if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);// 如果插入新节点后链表长度大于8,则判断是否需要树化,因为第一个元素没有加到binCount中,所以这里-1if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}// 如果待插入的key在链表中找到了,则退出循环if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}// 如果找到了对应key的元素if (e != null) { // existing mapping for key// 记录下旧值V oldValue = e.value;// 判断是否需要替换旧值if (!onlyIfAbsent || oldValue == null)// 替换旧值为新值e.value = value;// 在节点被访问后做点什么事,在LinkedHashMap中用到afterNodeAccess(e);// 返回旧值return oldValue;}}// 到这里了说明没有找到元素// 修改次数加1++modCount;// 元素数量加1,判断是否需要扩容if (++size > threshold)// 扩容resize();// 在节点插入后做点什么事,在LinkedHashMap中用到afterNodeInsertion(evict);// 没找到元素返回nullreturn null;
}
(1)计算key的hash值;
(2)如果桶(数组)数量为0,则初始化桶;
(3)如果key所在的桶没有元素,则直接插入;
(4)如果key所在的桶中的第一个元素的key与待插入的key相同,说明找到了元素,转后续流程(9)处理;
(5)如果第一个元素是树节点,则调用树节点的putTreeVal()寻找元素或插入树节点;
(6)如果不是以上三种情况,则遍历桶对应的链表查找key是否存在于链表中;
(7)如果找到了对应key的元素,则转后续流程(9)处理;
(8)如果没找到对应key的元素,则在链表最后插入一个新节点并判断是否需要树化;
(9)如果找到了对应key的元素,则判断是否需要替换旧值,并直接返回旧值;
(10)如果插入了元素,则数量加1并判断是否需要扩容;
HashMap的put方法讲解相关推荐
- RestTemplate使用实战-exchange方法讲解-HTTP请求
RestTemplate使用实战-exchange方法讲解 2019-10-28 12:40:51 阅读:160 来源: 互联网 标签:HTTP 请求 exchange RestTemplate ...
- python列表方法语句_Python中列表和元组的相关语句和方法讲解
列表(list): 首先,列表属于序列,那么序列类型可用如下内建函数-- list(iter):把可迭代对象转换为列表. str(obj):把obj对象转换为字符串,即用字符串来表示这个对象. tup ...
- Nginx访问控制_IP访问控制(http_access_module)原理、局限性、解决方法讲解
Nginx访问控制_IP访问控制(http_access_module)原理.局限性.解决方法讲解 参考文章: (1)Nginx访问控制_IP访问控制(http_access_module)原理.局限 ...
- HashMap的遍历方法
使用工具 IDEA2018.2 使用说明 使用迭代器,即创建Iterator对象,Iterator是一个接口,也有泛型 hasNext方法判断是否已经遍历完, next方法取当前遍历的对象 HashM ...
- Py之pandas:pandas的read_excel()函数中各参数说明及函数使用方法讲解
Py之pandas:pandas的read_excel()函数中各参数说明及函数使用方法讲解 目录 pandas的read_excel()函数中各参数说明及函数使用方法讲解 read_excel()函 ...
- linux的python2.7的paramiko_Python使用paramiko操作linux的方法讲解
paramiko介绍 paramiko是一个基于python编写的.使用ssh协议的模块,跟xshell和xftp功能类似,支持加密与认证,可以上传下载和访问服务器的文件. 可以利用paramiko模 ...
- java 语言如何判断素数_C语言实验之判断素数(循环结构java)方法讲解
C语言实验之判断素数(循环结构java)方法讲解 Problem Description 从键盘上输入任意一个正整数,然后判断该数是否为素数. 如果是素数则输出"This is a prim ...
- 小米手机系统服务组件是干什么的_怎么查看小米手机MIUI系统的基本功能-小米手机MIUI系统基础功能查询方法讲解...
小米手机是国产品牌手机中口碑较好的手机之一,受到大家的喜爱,配置功能丰富,价格实惠.亲们或许都不知道怎么查看小米手机MIUI系统的基本功能,小编很高兴为大家解决这个问题,接下来就为大家奉上小米手机MI ...
- HashMap的使用方法详解
HashMap是一种十分常用的数据结构对象,可以保存键值对,下面将详细介绍HashMap的使用方法. 一.添加方法 put方法,可以单次向HashMap中添加一个键值对. 注意:添加到Map中的数据, ...
最新文章
- 保研夏令营的个人陈述怎么写?
- 使用结构体输出员工工资表
- python多线程同步与互斥_Python之多线程:线程互斥与线程同步
- python 数值运算 m op n_python数值运算 四则运算
- python 监视图_python获取zabbix监控图
- hexo的landfarz主题侧栏靠左
- TEN网格数据导入oracle,开源-Solidity 分散的oracle网络的示例链链接。-糯米PHP
- office2010过期解决办法
- 基于低代码平台实现物流行业的知识文档管理系统
- 天猫官方出品运营宝典-小二带你解读行业趋势
- 19c(19.3) 单机数据库安装
- VMware虚拟机鼠标失灵怎么办
- 关于t00ls的挂机脚本
- 如何用Go语言创建WebSocket服务
- 第39天:WEB攻防-通用漏洞CSRFSSRF协议玩法内网探针漏洞利用
- acer 4750 Fn+亮度键(左右方向键亮度调节)无效问题的解决办法
- AutoJs学习-实现成语查询
- 火山视窗CEF浏览器用网页框架操作实现取本机IP、地址
- python中true是什么意思_Python解惑之True和False详解
- 蚂蚁金服崔恒斌:金融智能——对话机器人新形态