首页 > 其他分享 >HashMap详解

HashMap详解

时间:2022-10-31 23:12:54浏览次数:73  
标签:hash HashMap value 链表 详解 key null

HashMap详解

HashMap相关介绍

HashMap是Java中的比较常见的集合,主要存放的是键值对,以key-value的形式存储,不是线程安全的。它里面的存储的key和value可以为null值,但是key只允许有一个null值。HashMap是无序的,无法保证里面存储的键值对的有序性。jdk1.8之前的版本底层采用的是数组+链表的方式组成,jdk1.8之后采用的是数组+链表+红黑树的方式。数组具有查询效率高、插入、删除效率低,链表具有查询效率低,但是插入、删除效率高,HashMap采用这两种方式的结构,可以保证查询、插入、删除效率都得到保证。

HashMap数据结构

jdk1.8之后的版本使用数据+链表+红黑树的方式作为底层的数据结构,在链表长度大于阈值8之后,如果数组长度大于64时,才会转换成红黑树进行存储。阈值默认是8。下面我们介绍一下HashMap的设值过程:

  1. 我们在调用HashMap的put设值时,首先会对值进行hash操作。

    public V put(K key, V value) {
    	return putVal(hash(key), key, value, false, true);
    }
    
  2. 判断索引的数组位置是否为空,如果为空,则进行初始化,分配空间,进行扩容。

    if ((tab = table) == null || (n = tab.length) == 0)
    	n = (tab = resize()).length;
    
  3. 判断这个位置是否有值,如果没有值,则创建一个新的节点。

    if ((p = tab[i = (n - 1) & hash]) == null)
    	tab[i] = newNode(hash, key, value, null);
    
  4. 如果这个位置有值,则需要解决冲突

    • 首先判断链表的头,代码中的p,先判断hash值是否和我们的相同,如果hash值相同的话,在判断具体数值,如果相同,则先记录该位置,也就是代码中的e。

      Node<K,V> e; K k;
      if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        e = p;
      
    • 如果不同,那就需要遍历链表,jdk1.8之后的做了优化,链表太长时,会转换成红黑树,如果是TreeNode,则调用TreeNode的方法进行插入,此时就是采用的红黑树作为数据结构。

      else if (p instanceof TreeNode)
        e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
      
    • 如果不是TreeNode,则是用循环的方式遍历链表,如果有相同的链表节点,则记录该节点,代码中的e,如果没有相同的链表节点,则e为null,此时会创建一个新的Node,插入在链表最后。

      for (int binCount = 0; ; ++binCount) {
          if ((e = p.next) == null) {
              p.next = newNode(hash, key, value, null);
              if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                  treeifyBin(tab, hash);
              break;
          }
          if (e.hash == hash &&
              ((k = e.key) == key || (key != null && key.equals(k))))
              break;
          p = e;
      }
      
    • 最后判断e是不是null,e代表的是是否存在相同的值,存在,则记录的位置,不存在,则为null,如果存在,则会直接更新e记录的位置的值。

      if (e != null) { // existing mapping for key
          V oldValue = e.value;
          if (!onlyIfAbsent || oldValue == null)
              e.value = value;
          afterNodeAccess(e);
          return oldValue;
      }
      
    • 在循环遍历链表时,如果该节点是个新的节点,插入在链表最后,此时会判断链表的长度是否大于TREEIFY_THRESHOLD - 1,默认是8,如果大于8,则会调用转换成红黑树的方法,但是,方法里面还会判断数组长度是否大于MIN_TREEIFY_CAPACITY,默认是64,如果大于,则转换成红黑树。

      if ((e = p.next) == null) {
          p.next = newNode(hash, key, value, null);
          if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
              treeifyBin(tab, hash);
          break;
      }
      
      int n, index; Node<K,V> e;
      if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
          resize();
      

关注微信公众号「平哥技术站」, 每日更新,在手机上阅读所有教程,随时随地都能学习。

原文链接:https://monkey.blog.xpyvip.top/archives/hashmap-xiang-jie

标签:hash,HashMap,value,链表,详解,key,null
From: https://www.cnblogs.com/aibianchengya/p/16846233.html

相关文章

  • matlab最小二乘法数据拟合函数详解
    定义:最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与......
  • [Pyhton] SimPy 离散事件模拟框架详解 —— 以一个简单的汽车充电排队模拟为例
    目录一、背景知识二、SimPy讲解2.1SimPy概述2.2基本概念2.3一个汽车开开停停的例子2.4在走走停停过程中增加充电过程(过程交互)2.5共享资源三、后续参考链接附录二......
  • FlinkSql之TableAPI详解
    一、FlinkSql的概念核心概念Flink的TableAPI和SQL是流批统一的API。这意味着TableAPI&SQL在无论有限的批式输入还是无限的流式输入下,都具有相同的语义。......
  • Python开发 之 Python3打包(windows/linux)详解
    文章目录​​1、唠唠叨叨​​​​2、背景​​​​3、Python打包工具​​​​3.1、py2exe​​​​3.2、cx_Freeze​​​​3.3、PyInstaller​​​​4、Windows打包​​​​4.......
  • linux文档编辑的命令都有哪些?linux命令详解
    在Linux系统中,所有的操作都是需要执行命令才能完成的,可以说,命令的掌握程度对于Linux运维工程师来说至关重要,本篇文章将为大家介绍几个Linux文档编辑命令,以下是详细的内容:1......
  • JS定时器详解
    前端定时器详解一、简介JS是单线程,同一时间只能执行一个任务,其他任务就得排队,后续任务必须等到前一个任务结束才能开始执行。而有时候我们需要规定时间内做一件事,比如倒......
  • cat命令详解
    cat命令详解cat命令是linux下的⼀个⽂本输出命令,通常是⽤于观看某个⽂件的内容的;一.cat主要有三⼤功能:1.⼀次显⽰整个⽂件。$catfilename2.从键盘创建⼀个⽂件。......
  • SpringMVC入门(详解1)
    SpringMVC介绍:Springwebmvc属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:springMVC详解: 使用范围: 执行流程:架构:文字描述:用户发送请求......
  • Java算法基础 - 单链表详解(文末有配套视频)
    导航​​步骤1只用Java类能实现吗?​​​​步骤2类里面有顾客属性​​​​步骤3排队打饭​​​​步骤4从一个顾客联系到另一个顾客​​​​步骤5加一个next字段​......
  • kindeditor配置及功能实现详解
    ​ 1.编辑器修改(可选)1.1在 ueditor/config.json 中添加代码块    /* 上传word配置 */    "wordActionName":"wordupload",/* 执行上传视频的action......