IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java —— HashMap -> 正文阅读

[数据结构与算法]Java —— HashMap

????????HashMap的底层主要是基于数组和链表来实现的。

一、put过程

  1. 对 Key 求 Hash 值,然后再计算下标
  2. 如果没有碰撞,直接放入数组中
  3. 如果碰撞了,以链表的方式链接到后面
  4. 如果链表长度超过阀值(8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表
  5. 如果节点已经存在就替换旧值
  6. 如果数组已满(容量16*加载因子0.75),就需要 resize(扩容2倍后重排)

二、get过程????????

????????当我们调用 get() 方法,HashMap 会使用键对象的 hashcode 找到数组位置,找到之后,会调用keys.equals() 方法去找到链表中正确的节点,最终找到要找的值对象。

三、如何减少碰撞

????????原理是如果两个不相等的对象返回不同的 hashcode 的话,那么碰撞的几率就会小些。

????????提高碰撞下的寻址性能,可以不用二叉查找树,而选择红黑树?为什么不一直使用红黑树?

????????之所以选择红黑树是为了解决二叉查找树的缺陷:二叉查找树在特殊情况下会变成一条线性结构(这就跟原来使用链表结构一样了,造成层次很深的问题),遍历查找会非常慢。而红黑树在插入新数据后可能需要通过左旋、右旋、变色这些操作来保持平衡。引入红黑树就是为了查找数据快,解决链表查询深度的问题。我们知道红黑树属于平衡二叉树,为了保持“平衡”是需要付出代价的,但是该代价所损耗的资源要比遍历线性链表要少。所以当长度大于8的时候,会使用红黑树;如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。

(一)红黑树

  • 每个节点非红即黑
  • 根节点总是黑色的
  • 如果节点是红色的,则它的子节点必须是黑色的(反之不一定)
  • 每个叶子节点都是黑色的空节点(NIL节点)
  • 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)

四、解决 hash 碰撞还有那些办法?

????????开放定址法

????????当冲突发生时,使用某种探查技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的地址。按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、双重散列法等。

五、如果 HashMap 的大小超过了负载因子定义的容量怎么办?

????????HashMap 默认的负载因子大小为0.75。也就是说,当一个 Map 填满了75%的数组的时候,将会创建原来 HashMap 大小的两倍的 bucket 数组来重新调整 Map 大小,并将原来的对象放入新数组中。这个过程叫作 rehashing。

????????因为它调用 hash 方法找到新的 bucket 位置。这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为 <原下标+原容量> 的位置。

六、HashMap的Resize具体做了哪些事情呢?

  • 扩容:创建一个新的Entry空数组,长度是原数组的2倍。

  • ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。为什么要重新Hash呢?因为长度扩大以后,Hash的规则也随之改变。 

七、HashMap 与 HashTable 区别

????????线程安全性:HashTable 安全

????????效率不同:HashTable 要慢,因为加锁

????????Hashtable 使用了 synchronized,保证线程安全

八、CocurrentHashMap 与Hashtable?

????????我们知道 Hashtable 是 synchronized 的,但是 ConcurrentHashMap 同步性能更好,因为它仅仅根据同步级别对 map 的一部分进行上锁

????????ConcurrentHashMap 当然可以代替 HashTable,但是 HashTable 提供更强的线程安全性

????????它们都可以用于多线程的环境,但是当 Hashtable 的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。由于 ConcurrentHashMap 引入了分割(segmentation),不论它变得多么大,仅仅需要锁定 Map 的某个部分,其它的线程不需要等到迭代完成才能访问 Map。简而言之,在迭代的过程中,ConcurrentHashMap 仅仅锁定 Map 的某个部分,而 Hashtable 则会锁定整个 Map

????????CocurrentHashMap(JDK 1.8)

????????CocurrentHashMap 抛弃了原有的 Segment 分段锁,采用了 CAS + synchronized 来保证并发安全性。其中的 val next 都用了 volatile 修饰,保证了可见性。

????????最大特点是引入了 CAS

?????????CAS操作需要我们提供一个期望值,当期望值与当前线程的变量值相同时,说明还没线程修改该值,当前线程可以进行修改,也就是执行CAS操作,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量再尝试再次修改该变量,也可以放弃操作。

?????????CAS的ABA问题

????????并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,期望数据仍是A的时候,修改才能成功

????????并发2:将数据修改成B

????????并发3:将数据修改回A

????????并发1(下):CAS乐观锁,检测发现初始值还是A,进行数据修改

????????ABA问题可以使用带参数版本解决,在读取和替换时判断版本

????????上述并发环境下,并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,可能导致错误,这就是CAS引发的所谓的ABA问题。

????????CAS 使用实例

????????对 sizeCtl 的控制都是用 CAS?

????????在开始初始化的时候,首先判断sizeCtl的值,如果sizeCtl < 0,说明有线程在初始化,当前线程便放弃初始化操作。否则,将SIZECTL设置为-1,Hash表进行初始化。初始化成功以后,将sizeCtl的值设置为当前的容量值。

九、hashcode的生成过程

????????hashcode是通过将内部存储地址映射成一个整型值,这个整型值就是hashcode。

????????

十、hashmap为什么是2的次幂?

????????hashMap源码获取元素的位置:计算Entry对象保存在 table中的数组索引值:

????????返回的是某个hashcode对应的下标位置

static int indexFor(int h, int length) {

// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";

return h & (length-1);

}

????????解释:

????????h:为插入元素的hashcode

????????length:为map的容量大小

????????&:与操作 比如 1101 & 1011=1001

????????如果length为2的次幂 则length-1 转化为二进制必定是11111……的形式,在于h的二进制与操作效率会非常的快。

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章           查看所有文章
加:2021-08-13 12:32:05  更:2021-08-13 12:34:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:37:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码