本篇内容基于JDK 1.8

一、HashMap的put方法流程如下图

二、具体的源码分析

/*** Associates the specified value with the specified key in this map.* If the map previously contained a mapping for the key, the old* value is replaced.** @param key key with which the specified value is to be associated* @param value value to be associated with the specified key* @return the previous value associated with <tt>key</tt>, or*         <tt>null</tt> if there was no mapping for <tt>key</tt>.*         (A <tt>null</tt> return can also indicate that the map*         previously associated <tt>null</tt> with <tt>key</tt>.)*/
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
}
/*** Computes key.hashCode() and spreads (XORs) higher bits of hash* to lower.  Because the table uses power-of-two masking, sets of* hashes that vary only in bits above the current mask will* always collide. (Among known examples are sets of Float keys* holding consecutive whole numbers in small tables.)  So we* apply a transform that spreads the impact of higher bits* downward. There is a tradeoff between speed, utility, and* quality of bit-spreading. Because many common sets of hashes* are already reasonably distributed (so don't benefit from* spreading), and because we use trees to handle large sets of* collisions in bins, we just XOR some shifted bits in the* cheapest possible way to reduce systematic lossage, as well as* to incorporate impact of the highest bits that would otherwise* never be used in index calculations because of table bounds.*/
static final int hash(Object key) {int h;//通过hashCode()的高16位异或低16位实现return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
/*** Implements Map.put and related methods** @param hash hash for key* @param key the key* @param value the value to put* @param onlyIfAbsent if true, don't change existing value* @param evict if false, the table is in creation mode.* @return previous value, or null if none*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;//底层存储数据的数组tab为空,进行第一次扩容,同时初始化tabif ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//计算要存储数据的下标index,如果当前位置为null,直接插入if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;//tab[i]的首个元素就是key,直接覆盖if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;//tab[i]为TreeNode,进行红黑树的插入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);//链表长度大于8,转换为红黑树进行处理if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}//找到已经存在的key,直接覆盖if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;//数据插入完成,size超过了扩容的阀值(容量*负载因子),进行扩容if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}

总结:

1.底层存储数据的数组,在第一次put元素的时候初始化,同时发生第一次扩容;

2.相比较JDK 1.8之前的版本,JDK 1.8在链表长度大于8的时候,会转化为红黑树处理,主要是基于效率的考量;

HashMap的put方法原理相关推荐

  1. 蔚来一面:HashMap 的 hash 方法原理是什么?看完这篇还不懂HashMap的hash原理,那我要哭了~

    Warning:这是<Java 程序员进阶之路>专栏的第 55 篇.那天,小二去蔚来面试,面试官老王一上来就问他:HashMap 的 hash 方法的原理是什么?当时就把裸面的小二给蚌埠住 ...

  2. java部分基础知识 (二):计算机组成原理 原码 补码 反码 按位符 移位符 按位与 按位或 按位抑或 非 分析hashMap的put方法原理

    这里写目录标题 引言 符号位 正数的二进制计算 负数的二进制计算 按位符和移位符 按位符 移位符 分析hashMap运算符 byte和char 总结 引言 最近做完一个项目后,我忽然发现自己的基础并不 ...

  3. 详解HashMap的内部工作原理

    本文将用一个简单的例子来解释下HashMap内部的工作原理.首先我们从一个例子开始,而不仅仅是从理论上,这样,有助于更好地理解,然后,我们来看下get和put到底是怎样工作的. 我们来看个非常简单的例 ...

  4. HashMap底层实现和原理

    本文是在阅读知乎老刘作品后的整理.内容基于JDK1.7进行分析,1.8做的改动文章末尾进行讲解. 1. 基本要义 1.1 概述 Hashmap在Map派生中的位置 HashMap基于Map接口实现,元 ...

  5. 彻底理解HashMap的元素插入原理

    转载自   彻底理解HashMap的元素插入原理 HashMap,是Java语言中比较基础也比较重要的一种数据结构,由于其用途广泛,所以,Java的工程师在设计HashMap的时候考虑了很多因素. 通 ...

  6. Map实现之HashMap(结构及原理)(转)

    java.util包中的集合类包含 Java 中某些最常用的类.最常用的集合类是 List 和 Map.List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构 ...

  7. java map大小_Java中HashMap的size()方法: HashMap.size() - Break易站

    Java中的HashMap HashMap类的java.util.HashMap.size()方法用于获取哈希映射HashMap中映射的大小,该映射引用Map中键值对或映射的数量. 句法: Hash_ ...

  8. HashMap源码及原理

    HashMap 简介 底层数据结构分析 JDK1.8之前 JDK1.8之后 HashMap源码分析 构造方法 put方法 get方法 resize方法 HashMap常用方法测试 感谢 changfu ...

  9. HashMap底层实现及原理

    注意:文章的内容基于JDK1.7进行分析.1.8做的改动文章末尾进行讲解.       一.先来熟悉一下我们常用的HashMap: 1.HashSet和HashMap概述 对于HashSst及其子类而 ...

最新文章

  1. PHP strlen()函数和strpos()函数
  2. lunix下的redis数据库操作——hash(哈希)
  3. Matlab Robotic Toolbox V9.10工具箱(二):正/逆运动学
  4. STL 之accumulate,adjacent_difference,inner_product,partial_sum
  5. CoreML的入门例子
  6. Android开发之recyclerview布局加载不全的问题
  7. 前端学习(3333):ant design介绍按钮类型
  8. Java树形转扁平_js把树形数据转成扁平数据
  9. unubtu16.04解决etc文件误改导致无法使用sudo等指令问题
  10. 阶段面试题_关于文案、交易系统、付费渗透率、阶段性目标的面试题解答
  11. python 序列化模块_Python进阶-XII serialize(序列化)、序列化模块
  12. 最大功率跟踪mppt
  13. modbus协议的常用测试工具
  14. 华为海思芯片 10 年备胎史!
  15. 让Linux命令行更换颜色----PS1环境变量的使用小结
  16. mysql怎么读取数据,面试建议
  17. Win10修修补补日记:Win10周年更新再出BUG 淡定
  18. 90岁的褚时健退休了,我们能够从褚老身上学到些什么?
  19. ISE中如何将自己的verilog源代码.v或VHDL源代码.vhd封装打包成IP核?
  20. 一套关于 Django 的笔试题

热门文章

  1. 手把手教你 Creator 2.x 打包 Android APK(Mac篇)
  2. 为什么磁盘1次随机读需10ms
  3. DAY SIX -- ospf的不规则区域问题和链路状态通告LSA
  4. matlab memory 代数环,代数环概念 - MATLAB Simulink - MathWorks 中国
  5. webpack : 无法加载文件 C:\Users\骚恒\AppData\Roaming\npm\webpack.ps1,因为在此系统上禁止运行脚本。
  6. xshell如何使用阿里云秘钥远程连接
  7. NETPLIER : 一款基于概率的网络协议逆向工具(一)理论
  8. Android获取设备支持的编解码器
  9. 魔兽世界怀旧服2020年最新服务器列表,2020年2月15日魔兽世界怀旧服服务器的排队等待时间的真实数据...
  10. 业聚医疗第三次冲刺港交所上市,钱永勋、刘桂祯夫妇为实控人