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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 系统运维系列 之HashMap底层实现原理和应用 -> 正文阅读

[数据结构与算法]系统运维系列 之HashMap底层实现原理和应用

1 介绍

1HashMapJava中最常用的集合类框架,也是Java语言中非常典型的数据结构;
(2HashMap是基于哈希表的Map接口的非同步实现。元素以键值对的形式存放,并且允许null键和null值,因为key值唯一(不能重复),因此,null键只有一个;
(3HashMap不保证元素存储的顺序;
(4HashMap是线程不安全的。

2 HashMap的默认负载因子是0.75,而不是0.5或者是整数1呢?

临界值(threshold) = 负载因子(loadFactor) * 容量(capacity)
loadFactor是负载因子,表示HashMap满的程度,默认值为0.75f,也就是说默认情况下,当HashMap中元素个数达到了容量的3/4的时候就会进行自动扩容。

//code
void addEntry(int hash, K key, V value, int bucketIndex) {
	if ((size >= threshold) && (null != table[bucketIndex])) {
		resize(2 * table.length);
		hash = (null != key) ? hash(key) : 0;
		bucketIndex = indexFor(hash, table.length); 
	}
	createEntry(hash, key, value, bucketIndex);
}

HashMap其实是底层基于哈希函数实现的,但是哈希函数都有如下一个基本特性:根据同一哈希函数计算出的散列值如果不同,那么输入值肯定也不同。但是,根据同一散列函数计算出的散列值如果相同,输入值不一定相同。
两个不同的输入值,根据同一散列函数计算出的散列值相同的现象叫做碰撞。

为了避免哈希碰撞,HashMap需要在合适的时候进行扩容;默认的负载因子(0.75)在时间和空间成本之间提供了很好的权衡。更高的值减少了空间开销,但增加了查找成本。

//总结:1)负载因子不能太大,不然会导致大量的哈希冲突或者哈希碰撞;也不能太小,那样会浪费空间;
(2)阈值(threshold) = 负载因子(loadFactor) x 容量(capacity) 根据HashMap的扩容机制,他会保证容量(capacity)的值永远都是2的幂;为了保证负载因子x容量的结果是一个整数,这个值是0.75(4/3)比较合理,因为这个数和任何2的次幂乘积结果都是整数。

3 jdk8中HashMap为什么要引入红黑树?

1)解决jdk1.8以前hash冲突所导致的链化严重的问题,因为链表结构的查询效率是非常低的,他不像数组,能通过索引快速找到想要的值,链表只能挨个遍历,当hash冲突非常严重的时候,链表过长的情况下,就会严重影响查询性能;
(2)本身散列列表最理想的查询效率为O(1),当时链化后链化特别严重,他就会导致查询退化为O(n)为了解决这个问题所以jdk8中的HashMap添加了红黑树来解决这个问题,当链表长度>=8的时候链表就会变成红黑树。

4 HashMap和Hashtable计算hash的方法不同?

1HashMap计算hash:对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取模。
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
static int hash(int h) {
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
 }
 static int indexFor(int h, int length) {
        return h & (length-1);
 }2Hashtable计算hash:直接使用key的hashcode对table数组的长度直接进行取模。
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;

5 HashMap 多线程操作导致死循环问题?

1)当重新调整HashMap大小的时候,确实存在条件竞争,因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小;
(2)在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。

HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);

Hashtablesynchronized的,但是ConcurrentHashMap同步性能更好,因为它仅仅根据同步级别对map的一部分进行上锁;
ConcurrentHashMap当然可以代替HashTable,但是HashTable提供更强的线程安全性。

6 HashMap如何保存两个key相同的数据?

IdentityhashMap类利用哈希表实现Map接口,比较键(和值)时使用引用相等性代替对象相等性,也就是说key(value)比较的时候只比较两个key是否引用同一个对象,比较的是对象的地址。

一般Key的选择应为String等类型的数据,尽量不要使用引用数据类型。

参考资料:
https://blog.csdn.net/fengxi_tan/article/details/106629280 HashMap底层实现原理
https://blog.csdn.net/qq_29909965/article/details/78358066 hashmap出现重复key的情况
https://blog.csdn.net/qq_33732195/article/details/108121285?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-108121285-blog-78358066.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-108121285-blog-78358066.pc_relevant_default&utm_relevant_index=2 HashMap如何保存两个key相同的数据

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-16 11:26:43  更:2022-05-16 11:27:17 
 
开发: 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/26 1:32:15-

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