https://www.cnblogs.com/JzedyBlogs/p/10208295.html

写得非常好:

这个是Java1.8

--------------------------------

 public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
} static final int hash(Object key) {//hash函数,用于索引定位
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, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;//存储数据Node没有初始化,此时初始化
if ((p = tab[i = (n - 1) & hash]) == null)//(n-1)&hash用于定位,若为null,表明Node数组该位置没有Node对象,即没有碰撞
tab[i] = newNode(hash, key, value, null);//对应位置添加Node对象
else {//表明对应位置是有Node对象的,hash碰撞了
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))//碰撞了,且桶中第一个节点就匹配
e = p;//记录第一个节点
else if (p instanceof TreeNode)//碰撞了,第一个节点没有匹配上,且桶为红黑树结构,调用红黑树结构方法添加映射
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {//碰撞了 不为红黑树结构,那么是链表结构
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {//如果到了链表尾端
p.next = newNode(hash, key, value, null);//链尾添加映射
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st//链表长度大于TREEIFY_THRESHOLD值,转换为红黑树结构
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))//如果找到重复的key,判断该节点和要插入的元素key是否相等,如果相等,出循环
break;
p = e;//为了遍历,和e = p.next结合来遍历
}
}
if (e != null) { // existing mapping for key//key映射的节点不为空
V oldValue = e.value;//取出节点值记录为老的节点值
if (!onlyIfAbsent || oldValue == null)//如果onlyIfAbsent为false,或者老的节点值为null,赋予新的值
e.value = value;
afterNodeAccess(e);//访问后回调
return oldValue;
}
}
++modCount;//结构性修改记录
if (++size > threshold)//判断是否需要扩容
resize();
afterNodeInsertion(evict);//插入后回调
return null;
}

put流程

1.通过hash函数计算key的hash值,调用putVal方法

2.如果hash表为空,调用resize()方法创建一个hash表

3.根据hash值索引hash表对应桶位置,判断该位置是否有hash碰撞

  3.1 没有碰撞,直接插入映射入hash表

  3.2 有碰撞,遍历桶中节点

    3.2.1 第一个节点匹配,记录该节点

    3.2.2 第一个节点没有匹配,桶中结构为红黑树结构,按照红黑树结构添加数据,记录返回值

    3.2.3 第一个节点没有匹配,桶中结构是链表结构。遍历链表,找到key映射节点,记录,退出循环。
      没有则在链表尾部添加节点。插入后判断链表长度是否大于转换为红黑树要求,符合则转为红黑树结构

    3.2.4 用于记录的值判断是否为null,不为则是需要插入的映射key在hash表中原来有,替换值,返回旧值putValue方法结束

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

static final int hash(Object key) {//hash函数,用于索引定位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, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;//存储数据Node没有初始化,此时初始化if ((p = tab[i = (n - 1) & hash]) == null)//(n-1)&hash用于定位,若为null,表明Node数组该位置没有Node对象,即没有碰撞
tab[i] = newNode(hash, key, value, null);//对应位置添加Node对象else {//表明对应位置是有Node对象的,hash碰撞了
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))//碰撞了,且桶中第一个节点就匹配
e = p;//记录第一个节点elseif (p instanceof TreeNode)//碰撞了,第一个节点没有匹配上,且桶为红黑树结构,调用红黑树结构方法添加映射
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {//碰撞了 不为红黑树结构,那么是链表结构for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {//如果到了链表尾端
p.next = newNode(hash, key, value, null);//链尾添加映射if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st//链表长度大于TREEIFY_THRESHOLD值,转换为红黑树结构
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))//如果找到重复的key,判断该节点和要插入的元素key是否相等,如果相等,出循环break;
p = e;//为了遍历,和e = p.next结合来遍历
}
}
if (e != null) { // existing mapping for key//key映射的节点不为空
V oldValue = e.value;//取出节点值记录为老的节点值if (!onlyIfAbsent || oldValue == null)//如果onlyIfAbsent为false,或者老的节点值为null,赋予新的值
e.value = value;
afterNodeAccess(e);//访问后回调return oldValue;
}
}
++modCount;//结构性修改记录if (++size > threshold)//判断是否需要扩容
resize();
afterNodeInsertion(evict);//插入后回调returnnull;
}

Java HashMap的put操作(Java1.8)的更多相关文章

  1. Java HashMap的put操作(Java1.6)

    https://www.cnblogs.com/skywang12345/p/3310835.html // 存储数据的Entry数组,长度是2的幂. // HashMap是采用拉链法实现的,每一个E ...

  2. HashMap源码解析(java1.8.0)

    1.1 背景知识 1.1.1 红黑树 二叉查找树可能因为多次插入新节点导致失去平衡,使得查找效率低,查找的复杂度甚至可能会出现线性的,为了解决因为新节点的插入而导致查找树不平衡,此时就出现了红黑树. ...

  3. [翻译]Java HashMap工作原理

    大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...

  4. java对cookie的操作

    java对cookie的操作比较简单,主要介绍下建立cookie和读取cookie,以及如何设定cookie的生命周期和cookie的路径问题. 建立一个无生命周期的cookie,即随着浏览器的关闭即 ...

  5. Java学习笔记(二二)——Java HashMap

    [前面的话] 早上起来好瞌睡哈,最近要注意一样作息状态.       HashMap好好学习一下. [定义] Hashmap:是一个散列表,它存储的内容是键值对(key——value)映射.允许nul ...

  6. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  7. 【转】Java HashMap工作原理(好文章)

    大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...

  8. 【转】Java HashMap 源码解析(好文章)

    ­ .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...

  9. 转:Java HashMap实现详解

    Java HashMap实现详解 转:http://beyond99.blog.51cto.com/1469451/429789 1.    HashMap概述:    HashMap是基于哈希表的M ...

随机推荐

  1. 【转】如何修改 video 样式

    我们这里说的“修改 video 样式”并不是要自己实现一套 controls,而是尝试修改 video 的默认样式 隐藏全屏按钮 这个很容易查到 video::-webkit-media-contro ...

  2. (5)HomeAssistant 增加设备

    将设备添加到Home Assistant https://www.home-assistant.io/docs/configuration/devices/ configuration.yaml文件 ...

  3. ssh 免密码登录配置,及其原理

    1.废话不多说,先上图   2. 典型的RSA非对称加密 RSA加密算法是一种典型的非对称加密算法,它基于大数的因式分解数学难题,它也是应用最广泛的非对称加密算法,于1978年由美国麻省理工学院(MI ...

  4. Oracle报错ORA-16433非归档丢失redo无法启动的恢复过程

    [案例]Oracle报错ORA-16433非归档丢失redo无法启动的恢复过程 转惜纷飞 今天ML的群中女神和travel在纠结一个恢复的问题,11.2.0.3版本,非归档,大概是rm掉current ...

  5. Spring Security(八):2.4.3 Project Modules

    In Spring Security 3.0, the codebase has been sub-divided into separate jars which more clearly sepa ...

  6. 剑指offer——链表中倒数第k个结点

    输入一个链表,输出该链表中倒数第k个结点. class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned ...

  7. redis学习(九)——数据持久化

    一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的.所以,我们需要将内存中的数据持久 ...

  8. 在IDEA中构建Tomcat项目流程

    在IDEA中构建Web项目流程 打开你的IDEA,跟着我走! 第一步:新建项目 第二步:找到Artifacts 点击绿色的+号,如图所示,点一下 这一步很关键,目的是设置输出格式为war包,如果你的项 ...

  9. python实现本地图片上传到服务区

    本地图片上传到服务器,其本质上来讲,就是读取本地图片,复制到服务器,并返回服务器url 前端代码,用的form表单提交,form表单中包含两个文件选择表单元素,选择文件,点击提交按钮,提交form表单 ...

  10. Stochastic Optimization of PCA with Capped MSG

    目录 Problem Matrix Stochastic Gradient 算法(MSG) 步骤二(单次迭代) 单步SVD \(project()\)算法 \(rounding()\) 从这里回溯到此 ...