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)
// 初始的判断
// resize() 初始数组 扩容 初始的时候 获取了一个容量为16的数组
n = (tab = resize()).length; // n 数组长度
// 确定插入的key在数组中的下标 15 11111
// 100001000111000
// 1111
// 1000 = 8
if ((p = tab[i = (n - 1) & hash]) == null)
// 通过hash值找到的数组的下标 里面没有内容就直接赋值
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash // hash值相同&&
// key也相同
((k = p.key) == key || (key != null && key.equals(k))))
// 插入的值的key 和 数组当前位置的 key是同一个 那么直接修改里面内容
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
// 转红黑树
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}

final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
// tab为空 或者 数组的长度小于64
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize(); // 扩容
else if ((e = tab[index = (n - 1) & hash]) != null) {
// 链表转红黑树的逻辑
TreeNode<K,V> hd = null, tl = null;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}

    final Node<K,V>[] resize() {
// [1,2,3,4,5,6,7,8,9,10,11,,,,]
Node<K,V>[] oldTab = table;
// 16
int oldCap = (oldTab == null) ? 0 : oldTab.length;
// 12
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 新的容量是 原来容量的两倍
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 扩容的临界值 原来的两倍 24
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
// 创建的数组的长度是32
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) { // 初始的时候是不需要复制的
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
// 数组中的元素就一个 找到元素在新的数组中的位置 赋值
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
// 移动红黑树节点
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
// 普通的链表的移动
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}

HashMap相关的更多相关文章

  1. 一张思维导图带你梳理HashMap相关知识

    HashMap可以说是java中最常见也是最重要的key-value存储结构类,很多程序员可能经常用,但是不一定清楚这个类背后的数据结构和相关操作原理,为了复习HashMap相关的知识,今天花了一天的 ...

  2. HashMap相关类:Hashtable、LinkHashMap、TreeMap

    前言 很高兴遇见你~ 在 深入剖析HashMap 文章中我从散列表的角度解析了HashMap,在 深入解析ConcurrentHashMap:感受并发编程智慧 解析了ConcurrentHashMap ...

  3. 问题(一)---线程池,锁、堆栈和Hashmap相关

    一.线程池: 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中 ...

  4. JDK源码分析(5)之 HashMap 相关

    HashMap作为我们最常用的数据类型,当然有必要了解一下他内部是实现细节.相比于 JDK7 在JDK8 中引入了红黑树以及hash计算等方面的优化,使得 JDK8 中的HashMap效率要高于以往的 ...

  5. HashMap相关总结

    1.HashMap:根据键值hashCode值存储数据,大多数情况下可以直接定位到它的值,但是遍历顺序不确定.所有哈希值相同的值存储到同一个链表中                         Ha ...

  6. HashMap 相关面试题及其解答

    Q:HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过 8 时,链表转换为红黑树. transient Node<K,V>[] ...

  7. HashMap相关(二)

    基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外, HashMap 类与 Hashtable 大致相同. ...

  8. LeetCode刷题笔记(2)HashMap相关应用

    1.问题描述 Example 1: Input: A = "this apple is sweet", B = "this apple is sour" Out ...

  9. JAVA中HashMap相关知识的总结(一)

    Java中HashMap在jdk1.7和jdk1.8中的区别点: 在jdk1.7中是用数组+链表形式存储,1.8采用数组+链表/红黑树形式 Jdk1.8中由链表转为红黑树是长度大于8,由红黑树转为链表 ...

  10. HashMap相关知识

    HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如此 ...

随机推荐

  1. Python实现北邮人论坛模拟登录

    推荐去我的博客里查看这篇文章,效果更佳: http://fuxuemingzhu.cn/2017/08/12/byrbbs-login/ 模拟登录北邮人论坛可能是每个学着写爬虫的北邮人必备技能了.在网 ...

  2. 【LeetCode】697. Degree of an Array 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 求出最短相同子数组度的长度 使用堆求最大次数和最小长 ...

  3. computer(hdu2196)

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  4. 响应式网页设计(Bootstrap)

    Bootstrap官网 AOS官网 Chrome官方教程 Chrome教程 Bootstrap官网中有许多Bootstrap网站示例,大家可以参考

  5. Histogram Processing

    目录 HISTOGRAM EQUALIZATION 代码示例 HISTOGRAM MATCHING (SPECIFICATION) 其它 Gonzalez R. C. and Woods R. E. ...

  6. vue安装使用v-chart时报错解决方案

    npm i v-charts echarts -S 1.在main.js中使用报以下错 liquidFill echarts/lib/visual/dataColor 找不到 出现此原因是因为版本问题 ...

  7. IM2603设计资料 Type-C拓展坞电源管理芯片

    应用于Type-C拓展坞外围集成Buck变换器的电源管理芯片 IM2603 IM2603 概述 用于带有集成降压转换器的 Type-C 外围应用的电源管理 IC IM2603 是一款主要用于 Type ...

  8. JS 在使用hasOwnProperty()函数时报错

    在使用hasOwnProperty()方法判断对象是否具有某种属性时eslint报下列错误: Do not access Object.prototype method 'hasOwnProperty ...

  9. LINUX学习-Mysql安装

    一.安装环境 操作系统CentOS6.8 关闭SeLinux和iptables防火墙 二.网络yum源 将下面的软件下载到  /etc/yum.repos.d/   的目录下 官方基础:http:// ...

  10. Numpy实现简单BP神经网络识别手写数字

    本文将用Numpy实现简单BP神经网络完成对手写数字图片的识别,数据集为42000张带标签的28x28像素手写数字图像.在计算机完成对手写数字图片的识别过程中,代表图片的28x28=764个像素的特征 ...