HashMap源码解析《三》get,remove方法

集合系列(三) -HashMap详解 关于HashMap,一直都是一个非常热门的话题,只要你出去面试,我保证一定少不了它! 阅读详情

1.hashmap中的get方法

   public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;     //根据得到结果取得值,如果不存在当前键则返回null,如果存在返回value值
    }
 final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) { //判断执行条件,数组初始划过并且长度大于0,并且当前hash对应的桶元素不为空
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;      //如果桶元素的hash值与当前hash相同,则返回当前桶元素
            if ((e = first.next) != null) {  //如果不是,且存在链表或者红黑树中存在数据,将桶元素执行的Node赋值给e
                if (first instanceof TreeNode)   //红黑树  红黑树查询
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {
                    if (e.hash == hash &&   //遍历寻找hash值相等,并且键值相等的Node并且返回
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;  //如果没有找到 则返回null;
    }

get方法总的来说没有put方法那么复杂,他不需要牵扯太多的数组变化,也无需在意是否到达阈值。只需要在寻找的时候,判断数组是否被初始化过,数组长度中是否有元素,并且当前的hash值在数组中存在下标索引,那么只需比对对应的Node,遍历整个链表,寻找hash值相等,并且键值相等的node,如果没有找到,则返回null.

与之相关的函数还有contiansKey方法;

    public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;    //如果存在,则返回Node值, 返回值为true;
    }

2,hashMap的remove方法

    public V remove(Object key) {
        Node<K,V> e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
            null : e.value;  //remove方法,如果找到那个Node,移除并且返回,如果没找到,返回null;
    }
 final Node<K,V> removeNode(int hash, Object key, Object value,
                               boolean matchValue, boolean movable) {
// matchValue 作用:区别remove(Key key)与remove(Key key,Value value) 如果matchValue为false,删除key相等的节点。
//如果为true则删除使需要key和value都相等
//movable 表示再删除节点的时候是否改变树的结构。如果为false,在删除的时候不移动,一般都为true只有在iterator的时候才为false;

     

  Node<K,V>[] tab; Node<K,V> p; int n, index; 
        if ((tab = table) != null && (n = tab.length) > 0 && (p = tab[index = (n - 1) & hash]) != null) {
                //判断数组是否初始化,是否存在元素,当前hash下标是否存在值; 
            Node<K,V> node = null, e; K k; V v; 
            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) 
                node = p;      //判断根节点是否是需要删除的节点,如果是赋值给node 
            else if ((e = p.next) != null) { 
                if (p instanceof TreeNode) //红黑树 
                    node = ((TreeNode<K,V>)p).getTreeNode(hash, key); 
            else { 
                do { 
           //遍历链表 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) { 
                       node = e; //如果找到 给node赋值 
                        break; 
                        }    
                     p = e; //否则继续遍历,但是保存当前值。p就是需要删除节点的前驱节点
                    } while ((e = e.next) != null); 
                }
            }
            //判断是否已经找到node ,是否需要比较value
           if (node != null && (!matchValue || (v = node.value) == value || (value != null && value.equals(v)))) {
                   if (node instanceof TreeNode) 
                        ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable); 
                    else if (node == p)//根节点就是要删除的那个节点,改变数组桶中存储的头结点,删除目标节点
                        tab[index] = node.next; 
                    else //表示需要删除的点是在链表中 
                           p.next = node.next; //让前驱节点越过当前节点,指向下一节点;
                      ++modCount; //修改次数增加 
                      --size; 
                      afterNodeRem oval(node); 
                      return node; 
                    } 
                   } 
            return null; 
        }



金现代面试题—— i++,++i, &&,&|自动装箱和自动拆箱(int,byte,float等)|取int等基本类型的最大值 public static void main(String[] args){ int i=1,j=1; if(i++==2&amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;++j==2){ i=7; } System.out.println(“i=”+i+”,j=”+j); } 请给出 输出结果: 阅读详情

相关推荐

不用写触发器!帆软填报报表自动记录创建/修改时间的终极方案

本文详细介绍了帆软填报报表中无需编写数据库触发器,即可自动记录数据创建时间和修改时间的终极方案。该方案利用帆软内置函数和单元格条件属性,在应用层实现日期自动生成,有效规避了触发器带来的权限、维护和部署难题,为数据填报提供了更轻量、灵活且易于维护的解决方案。

weixin_28040125的博客 359

Redis源码剖析之GEO——Redis是如何高效检索地理位置的?

Redis GEO 用做存储地理位置信息,并对存储的信息进行操作。通过geo相关的命令,可以很容易在redis中存储和使用经纬度坐标信息。Redis中提供的Geo命令有如下几个: geoadd:添加经纬度坐标和对应地理位置名称。 geopos:获取地理位置的经纬度坐标。 geodist:计算两个地理位置的距离。 georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。 georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。 geohash:计

xindoo 2053

IBM X3650 M4做raid阵列

步骤1.开机出现此界面,同时按ctrl键和h键,进入IBM X3650 M4配置raid界面。 【注】不知道是不是因为我的服务器长期闲置,按键ctrl键和h键居然无法进入raid配置界面。这时候,我们可以进bios同样可以进入raid配置界面。如果你按ctrl键和h键就可以直接进入raid配置界面,那么请忽略此段,直接看步骤2 开机,按键F1,选中system setting ,接着选中Adapters and UEFI Drivers ...

ani5565的博客 2万+

【集合-HashMap】源码级理解HashMap之get()和remove()方法

壹:get(Object key)方法 //调用getNode()方法,获取不到返回null,否则返回key对应的value public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; } //重点在这里 final Node<K,V> getNode(int hash, Object key)

蛙广志 587

《深入浅出强化学习原理入门》学习笔记(三)机器人找金币应用实例

《深入浅出强化学习原理入门》学习笔记(三)MDP应用实例

lxs3213196的博客 3187

数学建模 种群竞争模型 学习笔记

模型背景 应用场景 种群竞争模型 例如 s1=0.5,则表示对于供养甲的资源来讲,单位数量的乙的消耗为单位数量的甲的0.5倍,即表示乙对于该资源的占有能力是甲的0.5倍(即竞争力弱) 仿真结果及分析 (1)设置自然增长率 r1=r2=1 (2)改变自然增长率 r1=r2=0.3 (3)修改甲和乙的最大容量 n1=10000, n2=100 (4)修改甲和乙的初始数量 x1=10, x...

Test_tju的博客 2028

【JAVA8】map操作 & 删除元素的简单方法

https://blog.youkuaiyun.com/cheidou123/article/details/86630168 https://blog.youkuaiyun.com/jackyrongvip/article/details/89397513 JAVA8-删除元素 传统的,在JAVA中得MAP中删除元素,可以这样,假设有个MAP: Map<Integer, String> map...

z69183787的专栏 8727

深入理解光流法外推雷达回波

背景介绍 鉴于本人实在太过疲惫和劳累,一些简单的便于理解的废话就不在记录,耗费两天时间研究了一下光流法,本帖用于记录学习过程中源码的难点细节。 使用光流预测的核心有两个利用多张连续回波图像(变分)或者相邻两张回波图(交叉相关,LK等)计算出光流场(速度矢量场),之后利用半拉格朗日方法进行外推。 半拉格朗日方法 三时间步半拉格朗日方法,其核心公式如下 但这个有点难理解,但看一维的图就很好理解 它的核心就是迭代求Am(位移矢量),如果理解困难的话,其实质上就是通过未来迭代(猜)出当前时刻的Am找到过去的假设

weixin_44695861的博客 6033

Java中的Map集合

目录 什么是Map集合 Map集合的子类 Entry Map集合的常用方法 1.把指定的键值对添加到Map集合中 2.根据指定的键删除对应的键值对 3. 根据指定的键返回对应的值 4.判断集合中是否包含指定的key 5.通过keySet键找值的方式遍历Map集合 6.通过entry对象找键值对的方式遍历Map集合 什么是Map集合 1.Map集合是一个双列集...

我能在河边钓一整天的鱼 1680

Surface Go 2 变身 Linux 开发本:保姆级 Ubuntu 20.04 双系统安装与驱动配置全攻略

本文详细介绍了如何将 Surface Go 2 变身为高效的 Linux 开发本,涵盖 Ubuntu 20.04 双系统安装、专用内核配置、驱动优化等全流程。通过 linux-surface 内核安装和硬件驱动优化,确保 Surface Go 2 的触控、笔输入、摄像头等功能完美运行,适合开发者打造便携生产力工具。

weixin_30596165的博客 616

【数据湖仓】:Iceberg、Hudi 和 Paimon 对比

适用于需要多计算引擎支持和复杂查询的离线批处理场景。其中立性和灵活性使其成为构建新型数据平台的理想选择。:在需要高频数据更新和高效小文件管理的场景中表现出色,适合实时数据处理和增量数据更新的业务需求。:专为实时流式数据处理设计,适用于对数据实时性要求高的业务场景,如实时数据分析和实时指标监控。通过以上分析,可以看出 Apache Iceberg、Apache Hudi 和 Apache Paimon 各有其独特的优势和适用场景。企业应根据自身业务需求和技术栈选择合适的数据湖仓方案,以充分发挥其价值。

欢迎来到我的博客,一起探索代码里的世界! 1609

Java基础语法—HashMap(哈希表)

创建hashmap对象 HashMap<String,Integer> hashMap = new HashMap<>(); 添加键值对 如果key已经存在,则返回旧的value,并将新的value存到该key中,如果key不存在,返回null 1、put方法:覆盖原有的value hashMap.put(key,value); 2、putIfAbsent方法:不会覆盖原有的value。 hashMap.putIfAbsent(key,value); 该方法首先

kuangd_1992的博客 2934

RSL-RL:开源人形机器人强化学习控制研究库

摘要:RSL-RL是一款专为机器人领域设计的开源强化学习库,其核心特点是紧凑性、可修改性和高性能。该库聚焦PPO和BC两大主流算法,并整合了对称性增强、好奇心驱动等机器人专用技术。通过纯GPU训练优化,RSL-RL在大型仿真中展现出卓越的吞吐性能,已成功应用于腿足运动控制、全身协调等多个机器人研究场景。其轻量级架构包含运行器、算法和网络三个可独立修改的组件,支持TensorBoard等主流日志工具。该框架特别适合需要快速原型开发的机器人研究者,但不适用于通用机器学习基准测试。开源地址:https://git

2506_90492529的博客 1674

HashMap的使用:put、remove和get方法原理

table是一组头结点数组n赋值为数组长度i = (n - 1) & hash按位与求出该key所在头结点数组的位置(哈希碰撞)p为找到的头结点e为最终找到的key对应的节点TREEIFY_THRESHOLD为8int n, i;//n为数组长度if ((p = tab[i = (n - 1) & hash]) == null) //(n - 1) & hash按位与求出该key所在头结点数组的位置//没有找到时,链表新创建一个节点else {K k;e = p;

碎格子 2202

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

HashMap源码解析【原来这么简单】

数组+链表(散列表)+红黑树在散列表中有装载因子这么一个属性,当装载因子*初始容量小于散列表元素时,该散列表会再散列,扩容2倍!装载因子的默认值是0.75,无论是初始大了还是初始小了对我们HashMap的性能都不好装载因子初始值大了,可以减少散列表再散列(扩容的次数),但同时会导致散列冲突的可能性变大(散列冲突也是耗性能的一个操作,要得操作链表(红黑树)!装载因子初始值小了,可以减小散列冲突的可能性,但同时扩容的次数可能就会变多!初始容量的默认值是16初始容量过大,那么遍历时我们的速度就会受影响~

风一样 979

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

HashMap源码解析

正是因为这样巧妙的 rehash 方式,既省去了重新计算 hash 值的时间,而且同时,由于新增的 1bit 是 0 还是 1 可以认为是随机的,在 resize 的过程中保证了 rehash 之后每个桶上的结点数一定小于等于原来桶上的结点数,保证了 rehash 之后不会出现更严重的 hash 冲突,均匀的把之前的冲突的结点分散到新的桶中了。例如:原来集合的元素个数是 6 个,那么 6/0.75 是8,是 2 的n次幂,那么新的数组大小就是 8 了。5 是假设计算出来的原来的索引。

在青海看海的企鹅的博客 1465

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

HashMap源码解析超详细

HashMap源码解析超详细

weixin_43691942的博客 1960

Java集合之HashMap源码解析

总结:查询调用get时在hash值形同的位置上遍历链表,对比每个链表的key,用==或者equals方法寻找key相同的对象取出,当链表的next方法返回为null时表示到了链表结尾处,此处null表示entry对象没有取到来判断链表结束,不是键值对中的value为null,value是在entry对象的value中存储hashMap没有修改方法,插入时会直接替换原来的值。createEntry方法很简单,就是将原本在数组中存放的链表头置入到新的Entry之后,将新的Entry放入数组中。

XING的博客 980

HashMap:内部组成&put:、get、remove方法大致逻辑&总结

源码基于java1.8 一、传统 HashMap的缺点 (1)JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。 (2)当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。 (3)针...

wzk! 1154

hashmap底层原理(数据结构 put原理 get原理 remove原理)

HashMap 数据结构为,其中:链表的节点存储的是一个 Entry 对象,每个Entry 对象存储四个属性HashMap实现采用Entry数组来存储key-value对(数组默认大小为0),每一个键值对组成了一个Entry实体,Entry类实际上是一个单向的链表结构,它具有Next指针,可以连接下一个Entry实体JDK1.8 版本的HashMap,底层数据使用数组 + 链表/实现。满足链表长度超过8且数组长度大于64,才会将链表替换成红黑树才会树化。

qq_52897007的博客 1538

【Java】通俗易懂的HashMap源码解析

分析 HashMap 的初始化过程以及键值对的存储原理

qq_45797138的博客 830

Map - HashSet & HashMap 源码解析

本文主要对Map - HashSet & HashMap进行源码解析。

qq_63353796的博客 1031

HashMap(深入源码追踪)

一篇让你搞懂HashMap的几个最重要的知识点,往源码跟踪可以让我们很轻松应对所谓的一些八股面试题.

m0_65013257的博客 1158

HashMap源码阅读笔记

从源码的角度解析HashMap的关键操作,愿开卷有益!

空空空的博客 1008

HashMap及HashTable源码解析

2)若没有在table[i]位置找到相同的key,则添加key到table[i]位置,新的元素总是在table[i]位置的第一个元素,原来的元素后调用addEntry方法。//若没有在table[i]位置找到相同的key,则添加key到table[i]位置,新的元素总是在table[i]位置的第一个元素,原来的元素后移。//遍历table[i]位置的链表,查找相同的key,若找到则使用新的value替换掉原来的oldValue并返回oldValue。//计算在数组中的存储位置。

2401_88972074的博客 811
上一篇: HashMap源码解析《二》
下一篇: 关于Spring MVC中自定义类型转换器的方式
Embra_ce
博客等级 码龄9年 2粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值