红黑树

jdk1.8源码分析之HashMap

冷暖自知 提交于 2019-12-24 11:53:00
原文链接:https://segmentfault.com/a/1190000012926722?utm_source=tag-newest 1.概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap 。HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现。HashMap 允许 null 键和 null 值,在计算哈键的哈希值时,null 键哈希值为 0。HashMap 并不保证键值对的顺序,这意味着在进行某些操作后,键值对的顺序可能会发生变化。另外,需要注意的是,HashMap 是非线程安全类,在多线程环境下可能会存在问题。 在本篇文章中,我将会对 HashMap 中常用方法、重要属性及相关方法进行分析。需要说明的是,HashMap 源码中可分析的点很多,本文很难一一覆盖,请见谅。 2.原理 上一节说到 HashMap 底层是基于散列算法实现,散列算法分为散列再探测和拉链式。HashMap 则使用了拉链式的散列算法,并在 JDK 1.8 中引入了红黑树优化过长的链表。数据结构示意图如下: 对于拉链式的散列算法,其数据结构是由数组和链表(或树形结构)组成。在进行增删查等操作时,首先要定位到元素的所在桶的位置,之后再从链表中定位该元素。比如我们要查询上图结构中是否包含元素 35 ,步骤如下: 定位元素 35 所处桶的位置, index = 35 %

java 8 Hashmap深入解析 —— put get 方法源码

主宰稳场 提交于 2019-12-23 18:30:53
本文为原创博文,转载请注明出处,侵权必究! 每个java程序员都知道,HashMap是java中最重要的集合类之一,也是找工作面试中非常常见的考点,因为HashMap的实现本身确实蕴含了很多精妙的代码设计。   对于普通的程序员,可能仅仅能说出HashMap线程不安全,允许key、value为null,以及不要求线程安全时,效率上比HashTable要快一些。稍微好一些的,会对具体实现有过大概了解,能说出HashMap由数组+链表+RBT实现,并了解HashMap的扩容机制。但如果你真的有一个刨根问题的热情,那么你肯定会想知道具体是如何一步步实现的。HashMap的源码一共2000多行,很难在这里每一句都说明,但这篇文章会让你透彻的理解到我们平时常用的几个操作下,HashMap是如何工作的。   要先提一下的是,我看过很多讲解HashMap原理的文章,有一些讲的非常好,但这些文章习惯于把源代码和逻辑分析分开,导致出现了大段的文字讲解代码,阅读起来有些吃力和枯燥。所以我想尝试另一种风格,将更多的内容写进注释里,可能看起来有些啰嗦,但对于一些新手的理解,应该会有好的效果。 HashMap结构   首先是了解HashMap的几个核心成员变量(以下均为jdk源码): 1   transient Node<K,V>[] table;        //HashMap的哈希桶数组

源码速读及点睛:HashMap

时光毁灭记忆、已成空白 提交于 2019-12-23 01:31:57
Java 8 HashMap的分离链表 从Java 2到Java 1.7,HashMap在分离链表上的改变并不多,他们的算法基本上是相同的。如果我们假设对象的Hash值服从平均分布,那么获取一个对象需要的次数时间复杂度应该是 O ( N M ) O(NM)(原为 E ( N M ) E(NM),但数学期望应改为 E ( N 2 M ) E(N2M)疑有误,译者注)。 Java 8 在没有降低哈希冲突的度的情况下,使用 红黑树 代替 链表 ,将这个值降低到了 O ( log ( N M ) ) O(log⁡(NM))(与上同,疑有误,译者注)。 数据越多, O ( N M ) O(NM)和 O ( log ( N M ) ) O(log⁡(NM))的差别就会越明显。此外,在实践中,Hash值的分布并非均匀的,正如”生日问题”所描述那样,哈希值有时也会集中在几个特定值上。因此使用平衡树比如红黑树有着比使用链表更强的性能。 使用链表还是树,与一个哈希桶中的元素数目有关。 下面的代码展示了Java 8的HashMap在使用树和使用链表之间切换的阈值。 当冲突的元素数增加到8时,链表变为树; 当减少至6时,树切换为链表。 中间有2个缓冲值的原因是避免频繁的切换浪费计算机资源。 static final int TREEIFY_THRESHOLD = 8; static final int

HashMap原理(二)——jdk1.8中HashMap扩容底层代码和算法分析

放肆的年华 提交于 2019-12-22 16:24:16
记得曾经有个著名大师谁谁谁曾经说过:你有一个思想,我有一个思想,我们交换一下,一人就有两个思想;你有一个苹果,我有一个苹果,我们交换一下,一人还是一个苹果。那既然这样的话,用我的iPhone 7 换你的 iPhone 11 如何? 这次给大家带来的是HashMap原理第二篇之——HashMap扩容的底层代码和算法分析。需要说明的是本文是基于jdk1.8来进行展开的,今后有机会会和大家分享在jdk1.7中HashMap的实现方式和1.8有哪些区别(扩容方式是其中的区别之一)。有朋友会说,既然HashMap是基于数组+单向链表+红黑树的底层数据结构,链表可以无限地延伸啊,红黑树也可以不停滴往里面放东西啊,还扩容干什么?这样的说法既对也不对,说对是因为HashMap确实是基于单向链表和红黑树的,但是有没有想过不断地往链表上添加元素或者不断地往树里面加东西会怎么样?是不是会导致链表过长以及树的深度增大?是不是进而会提高遍历链表或者红黑树的时间复杂度?最终导致从表现上来看插入和查找操作会越来越慢?所以,到了一定程度对数组扩容还是很有必要的。那又有朋友会问:扩容很简单啊,需要的时候从数组两端往外延伸一下内存空间不就可以了吗?……想啥呢?数组不是拉面,需要的时候从两边往外抻一下,不存在的!数组扩容只能开辟出一个更大的内存空间出来,将原来的内容迁移到新的内存空间里面。OK

红黑树(RBTree)

ぐ巨炮叔叔 提交于 2019-12-21 04:22:34
RBTree 基于BST存在的问题,一种新的树——平衡二叉查找树(Balanced BST)产生了。平衡树在插入和删除的时候,会通过旋转操作将高度保持在logN。其中两款具有代表性的平衡树分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,在实际环境下的应用不如红黑树。 红黑树(Red-Black Tree,以下简称RBTree)的实际应用非常广泛,比如Linux内核中的完全公平调度器、高精度计时器、ext3文件系统等等,各种语言的函数库如Java的TreeMap和TreeSet,C++ STL的map、multimap、multiset等。 RBTree也是函数式语言中最常用的持久数据结构之一,在计算几何中也有重要作用。值得一提的是,Java 8中HashMap的实现也因为用RBTree取代链表,性能有所提升。 RBTree的定义 RBTree的定义如下: 1. 任何一个节点都有颜色,黑色或者红色 2. 根节点是黑色的 3. 父子节点之间不能出现两个连续的红节点 4. 任何一个节点向下遍历到其子孙的叶子节点,所经过的黑节点个数必须相等 5. 空节点被认为是黑色的 数据结构表示如下: class Node<T>{ public T value; public Node<T> parent; public boolean isRed; public Node<T>

c++面试总结

不问归期 提交于 2019-12-19 00:56:38
c++面试总结 1.算法 2.数据结构 3. C++ feature 4. OS 5. Network 6. Database 7. 实战 8.系统学习资料 8.1 数据结构 8.2 OS 8.3 Network 8.4 Database 8.5 Linux 8.6 C++ Programing 8.7 Other 8.8 面试指南 8.9 网站 1.算法 排序 冒泡排序 简单选择排序 直接插入排序 折半插入排序 希尔排序 快速排序 归并排序 堆排序 基数排序 计数排序 各种排序的时间复杂度,空间复杂度,是否稳定,时间复杂度是否与初始序列有关? 查找:二分查找,lower_bound, upper_bound 分治与递归:逆序对数,大数相加,大数相乘 贪婪算法 动态规划:背包问题,找零钱问题,最长公共子序列(LCS) BFS,DFS,最短路径(Dijkstra算法,Floyd算法) 字符串匹配算法:KMP算法,BM算法,Sunday算法 补充:Top-K算法,Bitmap算法, Bloom Filter算法,一致性哈希算法,8数码问题(A 算法,B 算法,IDA*算法) 2.数据结构 线性表:数组,栈,队列,链表特点以及应用场景。 数组:老鼠走迷宫问题,稀疏矩阵压缩 链表:单链表逆序,单链表去重,单链表删除结点(仅给出删除结点),两个链表交叉求交叉点

Java HashMap的put操作(Java1.8)

孤街浪徒 提交于 2019-12-17 09:04:16
https://www.cnblogs.com/JzedyBlogs/p/10208295.html 写得非常好: 这个是Java1.8 -------------------------------- 1 public V put(K key, V value) { 2 return putVal(hash(key), key, value, false, true); 3 } 4 5 static final int hash(Object key) {//hash函数,用于索引定位 6 int h; 7 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 8 } 9 10 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 11 boolean evict) { 12 Node<K,V>[] tab; Node<K,V> p; int n, i; 13 if ((tab = table) == null || (n = tab.length) == 0) 14 n = (tab = resize()).length;//存储数据Node没有初始化,此时初始化 15 if ((p = tab[i = (n - 1) & hash])

[Java复习] 集合框架 Collection

╄→гoц情女王★ 提交于 2019-12-17 08:36:15
Q1 Collection java的集合以及集合之间的继承关系? 数组和链表的区别? 固定长度,连续内存,不能扩展,随机访问快,插入删除慢。链表相反 List, Set, Map的区别? List,Set继承Collection接口 List可以放重复数据,Set不能,Map是k-v对 List和Map的实现方式以及存储方式? ArrayList: 底层动态数组。随机访问快,增删慢,线程不安全。 扩容导致数组复制,批量删除会导致找两个集合交集,效率低。 LinkedList: 底层链表(双向列表)。增删快,查找慢,线程不安全。 遍历: 1.普通for循环,元素越多后面越慢 2.迭代器:每次访问,用游标记录当前位置 根据下标获取node,会根据index处于前半段还是后半段进行折半,提升效率。 HashMap: 散列表, 数组+链表+红黑树(JDK1.8) 默认16, 扩容2的幂 Q2 List ArrayList实现原理? 动态数组,默认10,扩容grow(minCapacity),增加到1.5倍 ArrayList和LinkedList的区别,以及应用场景? 1.动态数组和双向队列链表。 2.ArrayList( 实现了RandomAccess接口 )用for循环遍历优于迭代器,LinkedList则相反。 3.ArrayList在数组任意位置插入,或导致该位置后面元素重新排列

数据结构九之红黑树

元气小坏坏 提交于 2019-12-17 06:55:09
红黑树也是一种自平衡的二叉搜索树 以前也叫做平衡二叉B树(Symmetric Binary B-tree) 红黑树必须满足以下 5 条性质 1、节点是 RED 或者 BLACK 2、根节点是 BLACK 3、 叶子节点(外部节点,空节点)都是 BLACK 4、 RED 节点的子节点都是 BLACK和父节点都是黑色,从根节点到叶子节点的所有路径上不能有 2 个连续的 RED 节点 5、从任一节点到叶子节点的所有路径都包含相同数目的 BLACK 节点 请问下面这棵是红黑树么? 红黑树必须满足以下 5 条性质 节点是 RED 或者 BLACK 根节点是 BLACK 叶子节点(外部节点,空节点)都是 BLACK RED 节点的子节点都是 BLACK ✓ RED 节点的 parent 都是 BLACK ✓ 从根节点到叶子节点的所有路径上不能有 2 个连续的 RED 节点 从任一节点到叶子节点的所有路径都包含相同数目的 BLACK 节点 上图的判断结果是否:他不是红黑树,五个性质满足了四个,但是第五条性质不满足, 红黑树的等价变换 红黑树 和 4阶B树(2-3-4树)具有等价性 ◼ BLACK 节点与它的 RED 子节点融合在一起,形成1个B树节点 ◼ 红黑树的 BLACK 节点个数 与 4阶B树的节点总个数 相等 ◼ 网上有些教程:用 2-3树 与 红黑树 进行类比,这是极其不严谨的,2

HashMap 完全解析

回眸只為那壹抹淺笑 提交于 2019-12-16 23:39:08
HashMap 完全解析 1. 基本特点 2. 存储结构 2.1 HashMap 数据底层具体存储的是什么? 2.2 为什么要用单链表的方式? 3. HashMap 的成员变量 4. 确定数组索引位置的 hash 算法 4.1 为什么要采用这种算法呢? 番外: 为什么用 & 操作呢? 为什么可以使用位运算(&)来实现取模运算(%)呢 5. 存储数据的 put 方法 6. HashMap 的扩容机制 7. 为什么HashMap线程不安全? 7.1 多线程 put,导致的数据不一致。 7.2 resize 造成的无限循环 参考 1. 基本特点 HashMap 是 java 中用于映射(键值对)处理的数据类型。基于哈希表的 Map 接口的实现。最多只允许一条记录的键为 null,允许多条记录的值为 null。 HashMap 不保证映射的顺序。特别是, 它不能保证顺序会随着时间的推移保持恒定 。 HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度 O(1)。 2. 存储结构 从结构实现来讲,HashMap 是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。 [图片上传失败…(image-7d8358-1576498907545)] 2.1 HashMap 数据底层具体存储的是什么? 通过查看 HashMap 的源码