HashMap1.8之节点删除分析
HashMap之节点删除
大家一直关注的都是HashMap如何添加节点,当节点数量大于8的时候转化为红黑树,否则使用链表等等,但大家是否有看过删除节点的处理逻辑呢? 今天来看看HashMap删除节点的神来之笔
问题来源
在查看HashMap源码时,有个以下字段,在删除的时候,判断节点数量,最多在小于6的时候,会untreeifying(树转化为链表),在点击这个字段时发现,只有在split()方法中使用,但split()方法在resize()方法中使用,与删除节点无关,遂去翻删除节点的代码逻辑

节点删除
通过remove方法,一路进来,找到删除节点的地方。如下图:

我们进入removeTreeNode方法中,代码如下:

查看方法注释,里面介绍到:如果节点太少,就会把当前bin转换成普通bin。不理解注释没关系,我们进入这个方法中唯一有转化的地方。进入untreeify()方法查看下。代码如下:

噢,第一行看一下,if,else看一下,嗯,这个方法就是获取返回了一个列表(这些方法都是TreeNode类里面的方法,所以请注意,this就是当前要操作的TreeNode节点)。到此明白,这个方法就是把红黑树转化成链表的,那么我的就得分析分析是如何操作的了,而没有使用到定义的全局变量。
删除判断逻辑分析

我们来分析分析上面这个逻辑,进入这个untreeify() 的要求是,root == null, root.right ==null, root.left==null, root.left.left==null四种情况,我们以7个节点的红黑树来分析,A为root节点。

所以进入这个方法主要有以下几种情况,我们一种一种的来分析当满足要求时,节点的个数。(这里默认认为知道红黑树的5个特点,主要是黑平衡)
当这四种情况都满足时,我们可以看出最多节点有如上图所示个数,可以为7个。(大于8个不考虑,因为大于8会变成红黑树)。
1. 最多节点情况:当我们删除节点D时,只满足root.left.left==null这个条件,这棵树仍可以维持红黑树的特点,这时的最大节点数为6.
2. 最少节点情况:当EFG不存在时,在A,B,C,D中删除任意一个节点,都会满足上述四种规则中的一种。则存在最少节点情况,有3个节点。
以上情况都是会将树转化成链表,此时的节点是 3<= nodes <=6 ,由此可以看出,当节点数在小于6时,是可能转化成链表,但不是绝对情况, 所以使用定义的变量(固定数量6)也不正确。只好通过判断去动态获取节点数。
节点数量原因分析
为什么在小于6的时候可能转换成链表,而在大于8的时候转化成红黑树?
主要通过时间查询节点分析,红黑树的平均查询时间为 log(n), 而链表是O(n),平均是O(n)/2。
当节点数为8时,红黑树查询时间3,链表查询时间是4, 可以看出来当红黑树查询效率大于了链表。(两个函数曲线问题,当节点更多是,比红黑树需要的时间更多)
当节点数为6时,为什么转换成链表,我认为主要时因为节点数太少,如果还是用红黑树,为了维持红黑树的特点,则需要翻转,左旋,右旋,等,更消耗性能。
为什么不是7是转化?
主要是为了给一个过渡,防止频繁转化。 也如上图,7个节点可能正好是一个满二叉树。
HashMap1.8之节点删除分析的更多相关文章
- 转载-HashMap1.8源码分析
原文地址-https://tech.meituan.com/2016/06/24/java-hashmap.html HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型.随着 ...
- 转载-HashMap1.7源码分析
原文地址-https://www.cnblogs.com/chengxiao/p/6059914.html HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重 ...
- HashMap1.8源码分析(红黑树)
转载:https://segmentfault.com/a/1190000012926722?utm_source=tag-newest https://blog.csdn.net/weixin_40 ...
- Java 集合系列之五:Map基本操作
1. Java Map 1. Java Map 重要观点 Java Map接口是Java Collections Framework的成员.但是它不是Collection 将键映射到值的对象.一个映射 ...
- java容器源码分析及常见面试题笔记
概览 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表. List Arraylist: Object数组 ...
- JDK1.8 HashMap 源码分析
一.概述 以键值对的形式存储,是基于Map接口的实现,可以接收null的键值,不保证有序(比如插入顺序),存储着Entry(hash, key, value, next)对象. 二.示例 public ...
- Device Tree(三):代码分析【转】
转自:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html Device Tree(三):代码分析 作者:linuxer 发布于:201 ...
- 数据结构之链表C语言实现以及使用场景分析
牢骚:本篇博客两个星期前已经存为草稿,鉴于发生一些糟糕的事情,今天才基本完成.本人6月份应届毕业生一枚,毕业后当天来到帝都,之后也非常顺利,面试了俩家公司都成功了.一家做C++方面电商ERP,一家做w ...
- lightning mdb 源代码分析系列(3)
本系列前两章已经描述了系统架构以及系统构建的基础内存映射,本章将详细描述lmdb的核心,外存B+Tree的操作.本文将从基本原理.内存操作方式.外存操作方式以及LMDB中的相关函数等几方面描述LMDB ...
随机推荐
- 计算机二级-C语言-程序设计题-190118记录-通过数组和指针两种方式对字符串进行处理。
//编写一个函数fun,比较两个字符串的长度,(不使用C语言提供的求字符串长度的函数),函数返回较长的字符串.若两个字符长度相同,则返回第一个字符串. //重难点:通过数组处理和通过指针进行处理的不同 ...
- Centos610安装Archiva
安装说明: https://www.cwiki.us/display/ArchivaZH/Linux+Installing+Standalone 1.下载地址 https://archiva.apac ...
- 队列的python实现
队列(queue),是一种操作受限的线性表.只允许在队列的一端添加元素,在队列的另一端删除元素.能添加元素的一端称为队尾,能删除元素的一端称为队头. 队列最大的特性是:先进先出(FIFO,first ...
- unittest和unittest2的区别差异、unittest2框架------执行原理
unittest和unittest2的区别差异 参考:https://pypi.org/project/unittest2/ unittest2是Python 2.7及更高版本中添加到unittest ...
- 解决 C# .NET WebClient WebRequest请求缓慢的问题
[编程环境]Visual Studio 2010, NET4.0 [开发语言]C#, 理论上VB.NET等依赖.NET Framework框架的语言均受此影响 [问题描述] 使用HttpWebRequ ...
- linux下的apache服务自启动的几种方式
1,如果是安装包安装在Linux系统下,那么可以使用 [root@localhost ~]# service httpd restart 从而可以开启或者重启apache服务 与此同时,它的标准方式是 ...
- C:gcc的基本使用
分布编译 预处理:gcc -E hello.c -o hello.i 编 译:gcc -S hello.i -o hello.s 汇 编:gcc -c hello.s -o hello.o 链 接:g ...
- centos8下gz,bz2,zip压缩解压缩
for gz 1.制作压缩包 [root@192 mnt]# tar czf mydir.tar.gz mydir1/ 2.解压gz 压缩包 [root@192 mnt]# tar xvf mydir ...
- 使用vASA842配置ASDM645
准备:使用VMware打开vASA842.ova文件,将第一个网络适配器桥接到一个vmnet接口,我这里是vmnet3,网段是10.0.0.0/24,网关是10.0.0.1/24 1.打开vASA84 ...
- Cisco AP-Mobility Express基础
Part I 介绍 1.1基本概况 Cisco Mobility Express这个名词出现在Cisco “8”系列的AP上,例如现在的AP1852,AP2802,AP3802等都是Mobility ...