前言:通常大家都知道HashMap的底层数据结构为数组加链表的形式,但其put操作具体是怎样执行的呢,本文通过调试HashMap的源码来阐述这一问题。

注:jdk版本:jdk1.7.0_51


1.put源码

 public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}

下面通过对源码调试具体说明put操作的流程。

2.具体调试过程

 public class CodeTest04
{
public static void main(String[] args)
{
String keyAa = "Aa";
String keyBB = "BB"; System.out.println("keyAa hashCode=" + keyAa.hashCode());
System.out.println("keyBB hashCode=" + keyBB.hashCode()); HashMap<String, String> hashMap = new HashMap<String, String>(); hashMap.put(keyAa, "abc");
// hashMap.put(keyBB, "abc");
hashMap.put(keyAa, "cba");
hashMap.put(keyAa,"def"); System.out.println(hashMap); }
}

说明:

不同内容的字符串,其hashCode是可能相等的。如字符串“Aa”和“BB”的hashCode相等(都是2112)。

②当执行上述代码13行和15、16行的时候,结果如下:

③当执行上述代码13行和14行时,结果如下:

通过上述结果,可得出如下结论:

①在key的hashCode相等,且key也相同的情况下,HashMap在执行put操作的时候,会进行覆盖操作,新值将覆盖旧值,所以最后输出为"{Aa=def}"。

②在key的hashCode相等,但key不相同(如"Aa"与"BB")的情况下,HashMap在执行put操作的时候,就会进行链表式存储,并且采用的是头插法,即新值处于链表头,最开始的值处于链表尾

#1.对于第一个结论,通过下面这段源码可以很清晰的了解其流程:

#2.对于第二个结果,key的hashCode相等,但key不同的情况,通过调试描述put的过程。

通过debug可以非常清晰的看出:当前hashmap中存在一对键值{"Aa"->"abc"},其key的hash值为2112,在put("BB","abc")的时候,发现其hash值也是2112,出现上文中描述的情况(key的hashCode值相等,当key的内容不同),因此会直接跳转。

注意i的值,这里的i表示put元素在hashmap底层数据结构中的索引值(可简单想象成元素在数组上的索引),因为"Aa"与"BB"的hashCode值相同,因此两次i的值都是。我们进入addEntry函数。

由于我们这里不需要扩容,因此会创建新的元素,注意此时桶的index为4,但是当前位置上已经存在"Aa"的键值对了,进入该函数。

这里可以清晰的看出,会取出之前bucketIndex=4上的键值对,也就是{"Aa"->"abc"},然后new一个Entry。

关键过程:把当前bucketIndex=4的值替换成了{"BB"->"abc"},并将其next的值赋值为{"Aa"->"abc"},这里就完成了头插法

总结

HashMap在进行put操作时,会有如下操作:

1)在key的hashCode相等,且key的内容也相同的情况下(两次"Aa"),就会对value值进行覆盖

2)在key的hashCode相等,但key的内容不相同的情况下("Aa","BB"),会进行链式存储,并且是头插法,新加的值("BB")在链表头,最开始("Aa")的值在链表尾。

3)在key的hashCode不相等的情况,直接进行散列存储。

4)从上述调试过程也发现,HashMap主要是以key为主,value相当于key的一个附属值,因为value随key走的。


by Shawn Chen,2018.6.8日,晚。

HashMap源码调试——认识"put"操作的更多相关文章

  1. HashMap源码分析(一)

    前言:相信不管在生产过程中还是面试过程中,HashMap出现的几率都非常的大,因此有必要对其源码进行分析,但要注意的是jdk1.8对HashMap进行了大量的优化,因此笔者会根据不同版本对HashMa ...

  2. HashMap 源码解析

    HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...

  3. JAVA源码分析-HashMap源码分析(一)

    一直以来,HashMap就是Java面试过程中的常客,不管是刚毕业的,还是工作了好多年的同学,在Java面试过程中,经常会被问到HashMap相关的一些问题,而且每次面试都被问到一些自己平时没有注意的 ...

  4. Java集合---HashMap源码剖析

    一.HashMap概述二.HashMap的数据结构三.HashMap源码分析     1.关键属性     2.构造方法     3.存储数据     4.调整大小 5.数据读取           ...

  5. 在Eclipse中进行HotSpot的源码调试--转

    原文地址:http://www.linuxidc.com/Linux/2015-05/117250.htm 在阅读OpenJDK源码的过程中,经常需要运行.调试程序来帮助理解.我们现在已经可以编译出一 ...

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

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

  7. 【JAVA集合】HashMap源码分析(转载)

    原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...

  8. HashMap源码解读(转)

    http://www.360doc.com/content/10/1214/22/573136_78188909.shtml 最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过 ...

  9. HashMap源码剖析

    HashMap源码剖析 无论是在平时的练习还是项目当中,HashMap用的是非常的广,真可谓无处不在.平时用的时候只知道HashMap是用来存储键值对的,却不知道它的底层是如何实现的. 一.HashM ...

随机推荐

  1. win10 uwp 商业游戏 1.2.1

    上一个游戏已经告诉大家如何写多个游戏,现在继续写这个无聊的游戏 希望大家在看这篇文章之前先看win10 uwp 商业游戏,在这个文章告诉了大家如何创建游戏. 修改数值 可以从上一篇的博客的游戏看到升级 ...

  2. SVN服务器本地搭建与使用

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6623026.html  使用SVN进行代码管理,需要搭建服务端资源库,然后在使用SVN的电脑安装SVN客户端或 ...

  3. python进程间通信

    Process之间有时需要通信,操作系统提供了很多机制来实现进程间的通信. 1. Queue的使用 可以使用multiprocessing模块的Queue实现多进程之间的数据传递,Queue本身是一个 ...

  4. Unix awk的流程控制BEGIN和END的讲解

    你可能对Unix比较熟悉,但你可能对Unix awk很陌生,这一点也不奇怪,的确,与其优秀的功能相比,awk还远没达到它应有的知名度. 流程控制语句是任何程序设计语言都不能缺少的部分.任何好的语言都有 ...

  5. AI产品经理成长路

    AI产品经理成长路 https://www.jianshu.com/p/4b98314ad3c0 以下都是自己平时知识的一些总结,只是一些个人的愚见,下面出现的公司.书籍.视频.网站都是自己看过体验过 ...

  6. IDEA项目搭建十三——服务消费端与生产端通信实现

    一.简介 之前已经完成了EurekaClient的服务生产者和Feign的服务消费者模块的搭建,现在实现统一的通信约定 (1) 统一Request结构 (2) 统一Response结构 (3) 统一E ...

  7. SD Consultant Year End Activities

    SD Consultant Year End Activities What are the year ending activities to be done for SAP SD?   S.No ...

  8. 7.Odoo产品分析 (二) – 商业板块(3) –CRM(1)

    查看Odoo产品分析系列--目录 CMR:Customer Relationship Management.企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的 ...

  9. Vue之resource请求数据

    导入resource文件 <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js& ...

  10. Gson解析空字符串异常的处理

    面对一些不规范的json,我们的gson解析经常会抛出各种异常导致app崩溃,这里可以采取一些措施来避免. 我们期望在后台返回的json异常时,也能解析成功,空值对应的转换为默认值,如:newsId= ...