IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java:HashMap源码解析 -> 正文阅读

[Java知识库]Java:HashMap源码解析

构造方法

构造方法

1、无参构造方法HashMap()

public HashMap() {
	//只指定了负载因子:默认的负载因子0.75。所有其他字段默认
	this.loadFactor = DEFAULT_LOAD_FACTOR; 
}

2、指定初始容量的构造方法HashMap(int initialCapacity)

public HashMap(int initialCapacity) {
	//初始容量为给定的int类型的数值,实际初始化的容量并不一定是给定的容量大小,实际的容量在扩容方法中说明
	//负载因子为默认负载因子0.75
	//调用指定初始化容量和负载因子的构造方法
	this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

3、构造方法HashMap(int initialCapacity, float loadFactor)

//指定初始容量和负载因子的构造方法
public HashMap(int initialCapacity, float loadFactor) {
	//如果给定的初始化容量小于0,抛出异常
	if (initialCapacity < 0)
		throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
	//int 类型的最大值2^31-1,入参为int类型的整数,所以给定的初始容量可能大于2^30(HashMap的最大容量)
	//如果给定的初始容量大于2^30,则将初始容量设置为2^30
	if (initialCapacity > MAXIMUM_CAPACITY)
		initialCapacity = MAXIMUM_CAPACITY;
	//如果负载因子小于等于0或者负载因子是一个NaN(Not-a-Number),抛出异常
	if (loadFactor <= 0 || Float.isNaN(loadFactor))
		throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
	//将传入的参数赋值给全局变量
	this.loadFactor = loadFactor;
	//调整初始化容量为大于等于且最接近给定的初始化容量的的二的整数次幂。
	//例如给定的初始化为17,那么会将初始化容量调整为32,32是2的5次幂,32是大于17并且是2的整数次幂中最接近17的
	// 0 <= initialCapacity <= 2^30
	this.threshold = tableSizeFor(initialCapacity);
}

调整初始化容量大小tableSizeFor(initialCapacity)

该方法在JDK11中与JDK1.8中的实现不一样。在JDK1.8中对n进行和五次右移和异或运算。
在JDK11中,调用的是Integer中的numberOfLeadingZeros(int i)方法,获取了n的二进制补码中最高位之前0的个数,对-1进行了一次右移。
在numberOfLeadingZeros(int i)方法中,没有了异或操作,并且对 i 右移的操作次数根据 i 的值决定,最多5次,最少1次。虽然对 1 进行了 4次左移,但是对1 进行左移操作效率比对一个随机整数进行右移操作效率要高。
该方法从JDK1.8到JDK11的升级提高了效率。

JDK11

该方法是为了将HashMap的容量调整为2的整数次幂。

//在调用该方法之前对对初始容量做了校验,所以调用该方法时,初始容量范围 0<= cap <= 2^30
static final int tableSizeFor(int cap) {
	/** 当 cap = 0时,传入numberOfLeadingZeros(int i)的值为-1,numberOfLeadingZeros(int i)的返回值为0。
	 * 此时n = -1,经过三目运算符,tableSizeFor(int cap)的返回值为 1。
	 * 即初始化时传入0,初始容量会变成1
	 */
	//当 0 < cap <= 2^30,numberOfLeadingZeros(int i)的 入参是一个小于2^30的非负整数
	//所以入参的补码的最高位之前至少有2个0。所以-1最少也要右移两位变成一个正数,并且-1右移之后的二进制数从最高位(左侧的第一个1)到最低位全为1
	//当且仅当入参为2^30-1时,n = 2^30-1
	int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
	//在最后做运算时 -1 <= n <= 2^30-1。是否可以去掉第二个三目运算符?
	return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

JDK1.8

该方法是为了将HashMap的容量调整为2的整数次幂

static final int tableSizeFor(int cap) {
	// -1 <= n <= 2^30-1,且n为整数
	int n = cap - 1;
	/**
	 * 当 -1 < n <= 2^30-1时,该运算将n从左边第一个1到最低位都变成1,最后三目运算中,将n变成2的整数次幂
	 * 当 n = -1时,经过以下运算后n是一个二进制补码全部为1的二进制数,即n = -1,最后在三目运算后 n = 1.
	 */
	n |= n >>> 1;//等价于 n = n | n >>> 1;
	n |= n >>> 2;
	n |= n >>> 4;
	n |= n >>> 8;
	n |= n >>> 16;
	//判断当n小于0时,设置初始化容量为1
	//当n大于等于0时,判断当n大于等于2^30时,设置初始容量为2^30
	//当n大于等于0并且小于2^30时,设置容量为n+1
	//经过运算可以确保返回值是大于等于1并且小于等于2^30的2的整数次幂
	return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 11:55:18  更:2021-08-19 11:56:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:25:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码