HashMap如何计算数组下标
讨论 代码环境为JDK1.8.0 211
HashMap如何计算数组下标
首先我们看看String的hashCode是如何计算的(出自JDK1.8.0 211 java.lang.String 1452行—1476行)
/*** Returns a hash code for this string. The hash code for a* {@code String} object is computed as* <blockquote><pre>* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]* </pre></blockquote>* using {@code int} arithmetic, where {@code s[i]} is the* <i>i</i>th character of the string, {@code n} is the length of* the string, and {@code ^} indicates exponentiation.* (The hash value of the empty string is zero.)** @return a hash code value for this object.*/public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}
String类重写了hashCode()函数,计算字符串的hashCode的公式为:
s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1] s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]
我们来举个例子:
经过debug我们得知三个字符串的hashCode()返回值,我们来通过计算公式模拟一下:
字符串“a”,长度n=1,字符‘a’=97,代入公式得:
s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]=97∗311−1=97s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1]=97*31^{1-1}=97 s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]=97∗311−1=97
字符串“ab”,长度n=2,字符‘a’=97,‘b’=98,代入公式得:
s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]=97∗312−1+98∗311−1=3105s[0]*31^{n-1}+s[1]*31^{n-2}+...+s[n-1]=97*31^{2-1}+98*31^{1-1}=3105 s[0]∗31n−1+s[1]∗31n−2+...+s[n−1]=97∗312−1+98∗311−1=3105
好了知道了如何计算String的hashCode,再来看看HashMap的hash()函数是如何利用hashCode的:
如果key对象为null的话,就返回一个0,当然String对象为null的话,强行计算hashCode()是会抛出空指针异常的。如果key对象不是为null,那么获取key的hashCode,然后与右移位16位后的hashCode进行异或操作(关于异或操作,总结:不同,结果为1,相同,结果为0),异或的结果就位hash()函数返回值。我们以String的hashCode()为例,图解计算一次hash()返回值:
通过debug,我们知道“my name is suser!”的hashCode返回值为:244633208,然后通过进制转换为二进制,方便计算
我们图解一下计算过程:
得到hash(key)=244629740后,下一步计算数组下标,我们看源码中第630行:
tab[i = (n - 1) & hash]
在JDK1.8中,HashMap底层为数组+链表或红黑树
i是什么?i就是数组下标;
n是什么?n是数组长度,默认为16
hash就是hash(key)函数的返回值,244629740为例,这里要得出下标,需要进行一次&(与运算)(同为1,则1,不然则为0)
这里,假设HashMap刚刚创建,也没有经过扩容操作,数组长度这时为默认的16,来算算下标:
最终计算得下标值为12。
下面,通过debug结果,给出证据,证明其下标值确定为12:
625行debug信息显示hash(key)返回值,key值等关键信息
630行debug信息显示此时HashMap数组长度为默认16,还未经过扩容操作
631行debug信息显示i的值为12,与我推想的结果一致
总结一下: HashMap中数组下标值的计算过程,大致分为如下几步:获取key.hashCode(),然后将hashCode高16位和低16位异或(^)操作,然后与当前数组长度-1结果进行与(&)操作,最终结果就是数组的下标值。
至于由于当前结点(键值对)的加入,导致当前HashMap中容量超过了阈值而扩容2倍,扩容后导致每个结点重新计算下标值(称为新下标值),新下标值只有两种可能:一、key的hash()返回值新加入与(&)操作计算的一位为0,则下标值与原下标值相同。二、key的hash()返回值新加入与(&)操作计算的一位为1,则计算出来的下标值=原下标值+原数组长度。
如果key对象为Integer,他的hashCode()直接返回的value。
HashMap如何计算数组下标相关推荐
- HashMap之数组下标计算
HashMap之数组下标计算 前提 loadFactor capacity threshold put时,数组下标计算 hash函数 putVal函数 核心计算 扩容时,下标的重置计算 前提 Hash ...
- 通过数组下标获取值都有哪些方法_通过面试题,让我们来了解Collection
前言 欢迎关注微信公众号:Coder编程 获取最新原创技术文章和相关免费学习资料,随时随地学习技术知识! 本章主要介绍Collection集合相关知识,结合面试中会提到的相关问题进行知识点的梳理.希望 ...
- 给定一个整数数组 nums和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。
问: /** 给定一个整数数组 nums和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数 ...
- 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
题目链接:https://leetcode-cn.com/problems/two-sum/solution/liang-shu-zhi-he-by-leetcode-2/ 给定一个整数数组 nums ...
- hashmap和数组哪个速度快
Chasel_s 最近去面试遇到了面试官问的很多问题,很多东西可能之后真正被人问过之后才会发现自己学了假的知识, 答对的就不说了,今天栽在java的数据结构上了,面试官今天问了我一个问题,数组和ha ...
- java,给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
标题:java,给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 一.示例 二.题解 方法一,暴力法:使用双重for循环,每 ...
- 两数之和, 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。
两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标. 可以假设每种输入只会对应一个答案.但是,数组 ...
- 第1题 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
package com.leetcode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; i ...
- byte[]数组下标的最大值
原以为int.MaxValue就是所有数组下标的最大值,编译也能通过,结果运行时发现报错:内存溢出. 经过测试发现,原来在不同的系统/不同的配置上,这个值都不太一样,我笔记本经过测试 byte[] b ...
最新文章
- typora新增主题,typora将主题导入本地
- 图解计算机中数据的表示形式
- java设计模式简述
- hibernate中持久化对象的生命周期(三态:自由态,持久态,游离态 之间的转换)...
- python中的数据类型有哪些是可阅读,Python中典型的数据类型中哪个只能阅读不能修改...
- nagios 使用mysql_Nagios监控MySQL
- (2021年)IT技术分享社区个人文章汇总(数据库篇)
- php html 停止工作,换行符php和html无法正常工作
- [No0000FD]C# 正则表达式
- ie9 jscript7 内存不足 页面无响应
- 本人见过的最有用的日志!不来转藏肯定后悔
- 一对一语音视频直播双端原生+php后台源码 社交交友APP匹配语音视频聊天即时通信源码
- android局域网怎么传文件,两手机同一局域网怎么传文件
- 如何拆分PDF成单页?这三个方法分享给你
- webview跳转第三方小程序
- centOS 8 报错:Failed to set locale, defaulting to C.UTF-8
- HPUX 11iV3 LVM新变化
- 阿里云大数据平台的实操:ODPS的SQL语句
- java毕业生设计在线辅导答疑系统计算机源码+系统+mysql+调试部署+lw
- MongoDB中不溜教程(1)简介与命令
热门文章
- 12306火车票订票项目源码
- php中抓取https页面,php抓取https url网页内容方法
- IDEA开发工具的安装及使用
- Flink的两阶段提交
- 【C++】【哈希表】【哈希函数】实现自己的哈希表,解决哈希冲突;动态哈希表;
- TCP UDP socket http webSocket 之间的关系
- List 根据下标删除元素
- 湖南文理计算机应用,三尺讲台迎冬夏 两寸笔头耕未来
----记湖南文理学院计算机科学与技术学院娄小平博士...
- AES加密原理及简单逆向解题思路 - 从0开始的repwn 02
- Snapshot Diagram画法小结