图片不够清晰?,点https://gitmind.cn/app/flowchart/f0c3178602查看高清图片,密码:7818

HashMap通过put()方法添加元素(List集合通过add()方法添加元素),元素插入的索引位置通过hash()计算key的hash值确定,插入的具体实现在putVal()方法中。

//当两个结点的key相同,则新节点的value会覆盖旧结点的value,并且会将旧的value返回
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);
}

计算hash值,并返回该hash值。

static final int hash(Object key) {int h;//如果key为null,则返回0,反之则返回key的hash值(key的hashCode值与key的hashCode值的高16位进行^异或运算得到的值)return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

Node节点元素插入的具体代码都在putVal()方法内。(这个方法很重要,建议搭配上面的流程图来看,一定要搞清楚,看完后自己可以用GitMind也画一个流程图,这样印象会很深刻

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {//Node数组       Node<K,V>[] tab; Node<K,V> p;  //p是临时结点int n, i;  //数组长度,索引// 数组未初始化或者长度为0,进行扩容if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// 确定元素存放在哪个桶中,桶为空,新生成结点放入桶中if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);// 桶中已经存在元素 : p(指向链表头节点)else {Node<K,V> e; K k;// 比较桶中第一个元素p与要插入元素的key是否相等,key相等则此次put为覆盖操作if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))// 将第一个元素赋值给e,用e来记录e = p;// key不相等且头节点p为红黑树结点,则此次put为向红黑树中插入节点else if (p instanceof TreeNode)//将节点添加到红黑树上e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);// key不相等;头节点p为链表结点,则此次put为向链表中插入节点(树化发生在此处)else {//遍历链表,有两种情况下才会跳出循环for (int binCount = 0; ; ++binCount) {//第一种:已经遍历到尾部,在尾部插入新结点跳出。(因节点数量+1 判断是否需要树化)/** 节点的下一个节点为null,说明遍历到了链表的最后一个节点,* 将当前遍历到的最后一个节点的next指向新插入节点*/if ((e = p.next) == null) {//在尾部插入新结点p.next = newNode(hash, key, value, null);//判断是否需要树化/*** 如果链表长度大于8,则需要树化**注意,binCount是从0开始的,并且执行这一步之前添加了一个新节点,此时链表长度为1+7+1=9.*     所以不要看着binCount >= TREEIFY_THRESHOLD - 1 = 7,就以为链表长度>=7就会红黑树化了*/if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st//并且数组长度>=64,则链表就会树形化(这些会在treeifyBin()方法中实现)treeifyBin(tab, hash);//跳出循环break;}// 第二种:e指向的节点与要插入节点的key相同,此次put为覆盖操作if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))//跳出循环break;//用于遍历桶中的链表,与前面的e = p.next组合,可以遍历链表p = e;}}//如果新节点不为空if (e != null) { // existing mapping for key//记录e的valueV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)//用新值替换旧值e.value = value;afterNodeAccess(e);//返回旧值return oldValue;}}++modCount;//添加新结点后,要判断数组的使用长度,如果达到临界值,那么数组就会扩容if (++size > threshold)resize();afterNodeInsertion(evict);return null;
}

插入节点元素时,遍历链表,当p.next ==null时,这个节点就是链表的尾节点,然后就可以通过修改尾节点元素的next指针指向,让next指针指向要插入的节点元素,这样我们的节点就顺利插入链表尾部了。 if语句中调用了newNode()方法,这个方法会根据传入的hash,key,value等参数,创建一个Node节点对象,并返回这个节点对象,这个节点对象就是我们要插入的节点元素

//节点的next指向为null,则该节点是尾节点
if ((e = p.next) == null) {//让最后一个节点next指针指向要插入的节点元素p.next = newNode(hash, key, value, null);//...此处省略...
}

根据传入的hash,key,value等参数,创建一个(non-tree)Node节点对象,并返回这个节点对象

// Create a regular (non-tree) node
Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {return new Node<>(hash, key, value, next);
}

Node<K,V>是一个静态内部类,实现了Map接口中的内部Entry接口

static class Node<K,V> implements Map.Entry<K,V> {final int hash;  //hash值final K key;     //keyV value;         //valueNode<K,V> next;  //指向下一个结点的next指针,(这是个单向链表,所以只有next指针,没有pre指针)Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}
}

HashMap底层分析_put添加元素相关推荐

  1. HashMap底层原理分析

    HashMap底层分析 一.JDK1.8之前 二.JDK1.8后 1.JDK1.8中的涉及到的数据结构 1.1 位桶数组 1.2 数组元素Node 一.JDK1.8之前   JDK1.8 之前 Has ...

  2. java map原理_Java HashMap底层原理分析

    前两天面试的时候,被面试官问到HashMap底层原理,之前只会用,底层实现完全没看过,这两天补了补功课,写篇文章记录一下,好记性不如烂笔头啊,毕竟这年头脑子它记不住东西了哈哈哈.好了,言归正传,今天我 ...

  3. HashMap 底层源码细致分析

    JDK集合HashMap 底层源码细致分析 前言 提示:对于初始 HashMap 的小伙伴来说,不推荐直接硬啃,建议先看一下如下几个视频教程之后再回头好好理解.(一遍看不懂则反复看,一小块一小块的找对 ...

  4. HashMap底层原理分析(put、get方法)

    1.HashMap底层原理分析(put.get方法) HashMap底层是通过数组加链表的结构来实现的.HashMap通过计算key的hashCode来计算hash值,只要hashCode一样,那ha ...

  5. 深度解剖HashMap底层原理

    HashMap底层原理 写在前面 JDK1.7版本--HashMap java.1.7源码分析 new一个HashMap实例的存储流程图如下: API常用方法 API中重要的变量 第一步:申明一个Ha ...

  6. JDK1.7中HashMap底层实现原理

    JDK1.7中HashMap底层实现原理 一.数据结构 HashMap中的数据结构是数组+单链表的组合,以键值对(key-value)的形式存储元素的,通过put()和get()方法储存和获取对象. ...

  7. java 的HashMap底层数据结构

    HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据 ...

  8. HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别(转)

    HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别 文章来源:http://www.cnblogs.com/beatIteWeNerverGiveU ...

  9. hashMap 底层原理+LinkedHashMap 底层原理+常见面试题

    1.源码 java1.7 hashMap 底层实现是数组+链表 java1.8 对上面进行优化 数组+链表+红黑树 2.hashmap 是怎么保存数据的. 在hashmap 中有这样一个结构 Node ...

最新文章

  1. 在Data Collector中使用TensorFlow进行实时机器学习
  2. oracle数据倾斜优化,Hive数据倾斜优化 - ericquan8的个人页面 - OSCHINA - 中文开源技术交流社区...
  3. SSM环境+jquery+ajax 实现批量文件上传并预览后,同时上传文件和数据 校验图片后缀是否合法 文件大小是否超限
  4. 银行代码就是银行行号吗?
  5. 2020年ESA中国区10m地表覆盖数据的镶嵌、裁剪与分省数据分享
  6. 柠檬班高级性能测试13期这个课老师讲的很细腻需要了解见正文
  7. IDEA 快捷键 代码上移一行 下移一行 快捷键 try catch 块 快捷键
  8. Java最新面试题及答案
  9. rem、em、px、rpx、vw、vh、%等
  10. 相位相关计算两张图片的平移量
  11. python 'NoneType' object has no attribute '_root'
  12. 本地docker不能登录远程harbor服务器,error response from daemon,error parsing http 403 response body
  13. 电子制造ERP管理系统在仓库管理中的应用
  14. 大话设计模式 第十一章 迪米特法则 小黑小白在开车
  15. bat批处理循环执行adb命令,非科班面试之旅
  16. RST切换成AHCI无法正常进入windows(装双系统Ubuntu)
  17. 爱我专业主题黑板报计算机,我爱我班主题黑板报
  18. Python学习交流群、python学习群、python技术交流群
  19. 温度控制模块项目总结
  20. 关于websocket做即时通信功能

热门文章

  1. 「雕爷学编程」Arduino动手做(20)—水银开关模块
  2. 关于移动端滚动穿透问题的解决
  3. 潭州课堂25班:Ph201805201 django框架 第五课 自定义简单标签,包含标签,模型类创建,梳理类创建 (课堂笔记)...
  4. Java中的变量数据类型补充
  5. 无边框模式对话框,设置鼠标拖动
  6. WPF的ComboBox 数据模板自定义
  7. FLASH得到MYSQL数据
  8. [Comet OJ - Contest #7 D][52D 2417]机器学习题_斜率优化dp
  9. MongoTemplate 使用aggregate聚合查询
  10. 微信小程序 自定义顶部状态栏