/**
* Initializes or doubles table size. If null, allocates in
* accord with initial capacity target held in field threshold.
* Otherwise, because we are using power-of-two expansion, the
* elements from each bin must either stay at same index, or move
* with a power of two offset in the new table.
* @return the table
*
*
*
* 初始化或者翻倍表大小。
* 如果表为null,则根据存放在threshold变量中的初始化capacity的值来分配table内存
* (这个注释说的很清楚,在实例化HashMap时,capacity其实是存放在了成员变量threshold中,
* 注意,HashMap中没有capacity这个成员变量)
* 。如果表不为null,由于我们使用2的幂来扩容,
* 则每个bin元素要么还是在原来的bucket中,要么在2的幂中
*
* 此方法功能:初始化或扩容
*/
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
//新的容量值,新的扩容阀界值
int newCap, newThr = 0;
//oldTab!=null,则oldCap>0
if (oldCap > 0) {
//如果此时oldCap>=MAXIMUM_CAPACITY(1 << 30),表示已经到了最大容量,这时还要往map中放数据,则阈值设置为整数的最大值 Integer.MAX_VALUE,直接返回这个oldTab的内存地址。
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
//如果(当前容量*2<最大容量&&当前容量>=默认初始化容量(16))
//并将将原容量值<<1(相当于*2)赋值给 newCap
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
//如果能进来证明此map是扩容而不是初始化
//操作:将原扩容阀界值<<1(相当于*2)赋值给 newThr
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
//进入此if证明创建map时用的带参构造:public HashMap(int initialCapacity)或 public HashMap(int initialCapacity, float loadFactor)
//注:带参的构造中initialCapacity(初始容量值)不管是输入几都会通过 “this.threshold = tableSizeFor(initialCapacity);”此方法计算出接近initialCapacity参数的2^n来作为初始化容量(初始化容量==oldThr)
newCap = oldThr;
else { // zero initial threshold signifies using defaults
//进入此if证明创建map时用的无参构造:
//然后将参数newCap(新的容量)、newThr(新的扩容阀界值)进行初始化
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) { //进入此if有两种可能
// 第一种:进入此“if (oldCap > 0)”中且不满足该if中的两个if
// 第二种:进入这个“else if (oldThr > 0)” //分析:进入此if证明该map在创建时用的带参构造,如果是第一种情况就说明是进行扩容且oldCap(旧容量)小于16,如果是第二种说明是第一次put
float ft = (float)newCap * loadFactor;
//计算扩容阀界值
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
//如果“oldTab != null”说明是扩容,否则直接返回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的实例
((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;//此对象接收会放在“j + oldCap”(当前位置索引+原容量的值)
Node<K,V> next;
do {
next = e.next;
//以下是扩容操作的核心,详情见我的博客:https://www.cnblogs.com/shianliang/p/9204942.html
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;
}

jdk1.8 HashMap的扩容resize()方法详解的更多相关文章

  1. 【Java】HashMap源码分析——常用方法详解

    上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ...

  2. 一万三千字的HashMap面试必问知识点详解

    目录 概论 Hasmap 的继承关系 hashmap 的原理 解决Hash冲突的方法 开放定址法 再哈希法 链地址法 建立公共溢出区 hashmap 最终的形态 Hashmap 的返回值 HashMa ...

  3. 【集合框架】JDK1.8源码分析之ArrayList详解(一)

    [集合框架]JDK1.8源码分析之ArrayList详解(一) 一. 从ArrayList字表面推测 ArrayList类的命名是由Array和List单词组合而成,Array的中文意思是数组,Lis ...

  4. (转)Spring JdbcTemplate 方法详解

    Spring JdbcTemplate方法详解 文章来源:http://blog.csdn.net/dyllove98/article/details/7772463 JdbcTemplate主要提供 ...

  5. C++调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

  6. JAVA 注解的几大作用及使用方法详解

    JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...

  7. Java提高篇——equals()与hashCode()方法详解

    java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...

  8. Java构造和解析Json数据的两种方法详解二

    在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Jso ...

  9. java基础(十六)----- equals()与hashCode()方法详解 —— 面试必问

    本文将详解 equals()与hashCode()方法 概述 java.lang.Object类中有两个非常重要的方法: public boolean equals(Object obj) publi ...

随机推荐

  1. WebSocket原理与实践(四)--生成数据帧

    WebSocket原理与实践(四)--生成数据帧 从服务器发往客户端的数据也是同样的数据帧,但是从服务器发送到客户端的数据帧不需要掩码的.我们自己需要去生成数据帧,解析数据帧的时候我们需要分片. 消息 ...

  2. VMware ESXI 6.5 安装及配置

    ---恢复内容开始--- 该文档是下载的LNV版 (Lenovo) VMware下载地址: 链接: https://pan.baidu.com/s/1X3-wR2fIjT6IsPre7R7w2Q   ...

  3. Android学习之基础知识六—Android四种布局详解

    一.Android基本布局 布局是一种可以放置多个控件的容器,它可以按照一定规律调整内部控件的位置,而且布局内部除了可以放置控件外,还可以放置布局,实现多层布局嵌套.布局和控件.布局和布局之间的关系如 ...

  4. Android BaseAdapter加载多个不同的Item布局时出现UncaughtException in Thread main java.lang.ArrayIndexOutOfBoundsException: length=15; index=15

    java.lang.ArrayIndexOutOfBoundsException: length=15; index=15 异常出现的场景:在做聊天界面时,需要插入表情,图片,文字,名片,还有几种较为 ...

  5. IDC Digital Transition Annual Festival(2018.10.19)

    时间:2018.10.19地点:北京万达文化酒店

  6. Ionic2 播放mp3功能实现

    在开发app的过程中有需要播放mp3的功能,一直想实现,但苦于具体的困难一直未能实现,经过一段时间的资料查询和测试,最终摸索出来,现记录如下: 1.最重要的是安装第三方插件ionic-audio,开源 ...

  7. 1kb的前端HTML模板解析引擎,不限于嵌套、循环、函数你能想到的解析方式

    传送门:https://github.com/xiangyuecn/BuildHTML copy之前说点什么 html做点小功能(什么都没有),如果是要手动生成html这种操作,容易把代码搞得乱七八糟 ...

  8. CentOS安装noVNC,以Web方式交付VNC远程连接

    什么是noVNC noVNC 是一个 HTML5 VNC 客户端,采用 HTML 5 WebSockets, Canvas 和 JavaScript 实现,noVNC 被普遍用在各大云计算.虚拟机控制 ...

  9. mysql 编码和汉字存储占用字节问题的探索

    MySql 5.5 之前,UTF8 编码只支持1-3个字节,只支持BMP这部分的unicode编码区,BMP是从哪到哪?基本就是 0000 ~ FFFF 这一区. 从MySQL 5.5 开始,可支持4 ...

  10. 修改sga_max_size大小后重启数据库报 ORA-00851

    http://blog.itpub.net/30150152/viewspace-1449898/