红黑树

【JDK】JDK源码分析-HashMap(1)

偶尔善良 提交于 2020-03-05 04:21:10
概述 HashMap 是 Java 开发中最常用的容器类之一,也是面试的常客。它其实就是前文「 数据结构与算法笔记(二) 」中「散列表」的实现,处理散列冲突用的是“链表法”,并且在 JDK 1.8 做了优化,当链表长度达到一定数量时会把链表转为红黑树。 因此,JDK 1.8 中的 HashMap 实现可以理解为「数组 + 链表 + 红黑树」。内部结构示意图: HashMap 的继承结构和类签名如下: public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {} PS: 还记得以前初读 HashMap 源码时,用了周末两天的时间,而且读完脑子里还是一头雾水。当时也没做什么笔记,这次记录一下。 代码分析 一些成员变量 // 默认初始化容量(必须是 2 的次幂) static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 // 最大容量(必须是 2 的次幂,且小于等于 2^30) static final int MAXIMUM_CAPACITY = 1 << 30; // 默认负载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f; //

HashMap源码深度解析

大城市里の小女人 提交于 2020-03-04 18:20:07
HashMap源码深度解析 一、重新认识HashMap 什么是HashMap? HashMap底层基于散列(Hash)算法,采用hash表实现键值对集合,继承了AbstractMap,实现了Map接口。最早出现在jdk1.2,允许null键和null值,null键的哈希值为0。需要注意的是HashMap不保证键值对顺序,同时非线程安全。 长啥样? 散列算法分为散列再探测和拉链式,HashMap采用的是拉链式,并在jdk1.8后使用红黑树优化长度大于等于8的链表。也就是说,目前HashMap底层数据结构为: 数组+链表+红黑树 。 数据结构如下图: 如上图所示,HashMap的数据结构采用数组和单链表(或者红黑树)组成,在进行增删改查时首先根据要查找元素的hash值定位到元素所在的数组下标(也称为桶),然后再根据这个桶所存储的元素的类型(单个node,单链表或红黑树)来找到该元素。 当单链表长度大于等于8时,转化为红黑树;当红黑树长度小于6时红黑树转化为链表。 HashMap特点 可以接受null键和null值,null键的hash值时0; 元素无序,可以序列化,线程不安全; 添加,查询的时间复杂度基本都是O(1); 存储元素时,根据键的hash值找到对应的桶。如果出现不同的对象计算出来的hash值相同,也就是hash冲突。为了解决这个问题

面试必问的HashMap改变了啥?

心不动则不痛 提交于 2020-03-03 01:25:57
微信公众号: Java修炼手册 关注可领取3T编程资料及面试题解。问题或建议,请公众号留言; 希望我的分享对你有所帮助 HashMap HashMap是面试必问的知识点之一,也是java开发最常用的一种数据模型,HashMap属于复合结构,以key-value形式存储数据,其中key是不允许重复的但是允许为空,value是可以重复或为空的,在jdk1.8前,它的结构为数组+链表,在jdk1.8后变成了数组+单向链表+红黑树 当JVM存储HashMap的K-V时,首先计算key的hash值,以此来确定插入的数组位置,但是这一hash值的位置可能已经存在有值,这时就顺延到同一hash值的元素的后面形成了单向链表,同一个链表上的Hash值是相同的,所以说数组存放的是链表!他的结构图: 红黑树的阈值是8,当链表大于等于8时链表变成了红黑树结构,大大减少了查找的时间。 这是源码的解释: 1 /** 2 * The bin count threshold for using a tree rather than list for a 3 * bin. Bins are converted to trees when adding an element to a 4 * bin with at least this many nodes. The value must be greater 5

红黑树基本操作

大城市里の小女人 提交于 2020-03-03 00:34:44
很早之前就想写一篇关于红黑树的文章,但是由于担心自己理解的不透彻,就一直不敢下笔。于是在重新看了很多篇文章和资料之后,决定彻彻底底的把红黑树搞清楚。也希望让你在面试中游刃有余。OK,废话不多说,开始今天的文章。 整篇文章的思路是这样的,红黑树其实就是一种数据结构,设计它的目的就是为了高效地进行增删改查,所以我们文章的顺序也会按照这个思路来进行。我们先从二叉查找树逐渐引入到红黑树,然后再详细的讲解。你如果看过其他文章想必也一定清楚,红黑树比较麻烦,希望你有点耐心,认真理解每一张图再往下分析。 一、二叉查找树 在正式开始了解红黑树之前呢,我们先来看一下二叉查找树的概念,从浅入深,希望你不要着急,下面就是是一颗二叉查找树: 从这张图我们会发现如下的规律: (1)左子树上所有节点的值均小于或等于它的根结点的值。 (2)右子树上所有节点的值均大于或等于它的根结点的值。 如果我们想要查找一个数字11,过程是怎么样的呢? 上面的过程已经很清晰了,在查找的时候,先与根节点比较,比根节点大则从右子树查找,比根节点小则从左子树查找,然后重复上面的过程,一直到找到我们需要的元素为止。 这个过程是查找操作,对于添加和删除呢?其实原理也是一样的,我们第一步就是找到我们需要插入的位置,然后把元素插入即可。这样看二叉查找树挺好的呀?别着急我们继续往下看这种情况。 如果我们在刚刚开始的时候还是以9为根节点

java集合框架-HashMap

拈花ヽ惹草 提交于 2020-03-02 22:21:43
JDK1.8前,HashMap底层使用数组和链表结合。首先通过key的hash值判断当前元素存放在数组的位置;如果该位置存在元素,则判断该元素与要存入的元素的hash值以及key是否相同,如果相同直接副高,不同就接到后面形成链表。 JDK1.8后,当一个数组位置的链表长度大于阈值(默认8)时,将链表转化为红黑树,减少搜索时间。 ps:TreeMap、TreeSet以及JDK1.8后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树在某些情况下会退化为线性结构的缺陷。 来源: oschina 链接: https://my.oschina.net/u/3991724/blog/3185425

红黑树操作

こ雲淡風輕ζ 提交于 2020-03-01 14:18:48
本文主要说明红黑树的插入和删除操作。 红黑树是满足以下性质的二叉搜索树: 1. 每个结点颜色或黑或红。 2. 根结点是黑色。 3. 每个叶结点(nil)为黑色。 4. 如果一个结点是红色,那么它的两个子节点都是黑色的。 5. 对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。 为了便于处理红黑树中的边界条件,使用一个颜色为黑色、其他属性任意的结点T.nil最为哨兵结点,让root的p和叶结点的left, right都指向T.nil。 插入操作: 设X为已经插入的结点,P为X的父结点,G为X的祖父结点,U为G的另一个子结点,即X的叔结点。 先将要插入的结点颜色设为红色,按照普通步骤插入结点之后可能破坏红黑树的性质,所以要进行修正。 破坏的性质可能是: 1. X和P都是红色,违反了性质4。 2. X是root,违反了性质2。 情况二只要将root重新变为黑色即可,下面主要考虑情况一。 如果P是G的左孩子,情况一的修正情况分为: 1. G为红色,P和U均为黑色:将G变为黑色、P和U变为红色即可。这种情况不用区分X是P的左孩子还是右孩子。完成之后虽然确保了X和P不是相邻的两个红色结点,但是G和G的父结点却又有可能称为相邻的红结点,所以将G变为X,进入下一轮循环。 2. G为黑色,P为红色,X为P的右孩子:将P左旋,变成情况3。这种情况不用考虑U的颜色。 3.

HashMap和ConcurrentHashMap

大城市里の小女人 提交于 2020-03-01 09:36:03
目录 HashMap Java7中HashMap(数组+单向链表) ​ Java8中的HashMap(数组+链表+红黑树) ConcurrentHashMap Java7中的ConcurrentHashMap Java8中的ConcurrentHashMap(引入红黑树) HashMap HashMap 根据键的 hashCode 值存储数据 ,大多数情况下可以直接定位到它的值,因而具有很快 的访问速度,但遍历顺序却是不确定的。 HashMap 最多只允许一条记录的键为 null ,允许多条记 录的值为 null。 HashMap 非线程安全 ,即任一时刻可以有多个线程同时写 HashMap,可能会导 致数据的不一致。 如果需要满足线程安全, 可以用 Collections 的 synchronizedMap 方法使 HashMap 具有线程安全的能力 ,或者 使用 ConcurrentHashMap 。 Java7中HashMap(数组+单向链表) 大方向上, HashMap 里面是一个 数组 ,然后数组中每个元素是一个 单向链表 。上图中,每个绿色 的实体是嵌套类 Entry 的实例, Entry 包含四个属性: key, value, hash 值和用于单向链表的 next 。 1. capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。

集合框架之HashMap(一)

半城伤御伤魂 提交于 2020-03-01 08:33:16
HashMap是非常重要的数据结构,并且大部分面试都会问到,优秀的java程序员应当要对HashMap进行深入的了解,今天我们就来剖析一下它。 目录 HashMap简介 成员变量 get和put的流程 hashMap相关的面试题 总结 一.简介 首先,HashMap是一个无序key,value集合,它的底层存储是由数组加链表和红黑树结构组成的的。在进行添加,删除和查找时,效率非常高,如果不考虑哈希碰撞,一次定位就能完成操作,时间复杂度为O(1)。 下面是一个默认长度的hashMap。 二.hashMap的成员变量 1.初始大小 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 这个是值是数组长度,也就是数组的初始最大行数,当然如果碰撞比较多,也有可能hashMap存了200个值,但是容量还是16。当然这不是理想状态。 2.最大值 static final int MAXIMUM_CAPACITY = 1 << 30; 这个没有什么好说的,hashMap最大容量。 3.增长因子 static final float DEFAULT_LOAD_FACTOR = 0.75f; 增长因子,就是如果数组被占用的大小超过当前大小的75%时,就进行扩容,按照当前容量二倍创建一个新的Entry

STL源码剖析学习十:红黑树的实现

隐身守侯 提交于 2020-02-29 05:39:27
STL源码剖析学习十:红黑树的实现 RB-Tree的节点设计: 节点设计分为两层: struct __rb_tree_node_base { typedef __rb_tree_color_type color_type; typedef __rb_tree_node_base* base_ptr; color_typr color; base_ptr parent, left, right; static base_ptr minimun(base_ptr x) { while (x->left != 0) x = x->left; return x; } static base_ptr maximun(base_ptr x) { while (x->right != 0) x = x->right; return x; } }; template<class value> struct __rb_tree_node:public __rb_tree_node_base { typedef __rb_tree_node<value>* link_type; value value_field;//关键是把节点的值独立出来 }; RB-Tree的迭代器: 也分两层,和slist的设计比较相似,比较特殊的是前进和后退的操作。 struct __rb_tree_base

【STL源码剖析读书笔记】【第5章】关联式容器之RB-tree

守給你的承諾、 提交于 2020-02-29 03:09:05
1、 二叉树:任何节点最多只有两个子节点,这两个子节点分别称为左子节点和右子节点。 2、 二叉搜索树:任何节点的键值一定大于其左子树中的每一个节点的键值,小于其右子树中的每一个节点的键值。 3、 红黑树不仅是一个二叉搜索树,还必须满足以下条件: 1) 每个节点不是红色就是黑色。 2) 根节点为黑色。 3) 如果节点为红色,其子节点必须为黑色。 4) 任意一个节点到到NULL(树尾端)的任何路径,所含之黑色节点数必须相同。 根据规则4) ,新增节点必须为红色;根据规则3),新增节点之父节点必须为黑色。当新增节点根据二叉搜索树的规则到达其插入点时,却未能符合上述条件时,就必须调整颜色并旋转树形,如下图: 4、 红黑树插入节点 先为某些特殊节点定义一些代名: X 代表新节点, P 为其父节点, G 为其祖父节点, S 为其叔父节点, GG 为其曾祖父节点。 插入操作分为以下几种情况: 一、 P 为黑 直接插入 X ,操作完成。 二、 P 为红 情况 1 : S 为黑且 X 为外侧插入。 对 P , G 做一次右旋转操作并改变 P , G 的颜色,即可。 情况 2 : S 为黑且 X 为内侧插入。 对 P , X 做一次左旋转操作并改变 G , X 的颜色,然后再对 G 做一次右旋转操作,即可。 情况 3 : S 为红且 X 为外侧插入。 对 P , G 做一次右旋转操作改变 X 的颜色