我是靠谱客的博主 懵懂果汁,最近开发中收集的这篇文章主要介绍java hashmap优势,谈谈 HashMap,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

java 7 HashMap

1. 经典的哈希表实现:数组+链表

数组优点:随机寻址是常数时间,无论数组长度多大,都可以通过硬件电路的线性地址变换查找。复杂度都是O(1)的。

哈希桶:本质是将一个元素映射到一个哈希值,致命问题是哈希碰撞

多个元素的哈希值相同称为哈希碰撞,解决办法是使用链表

成员变量中的 Entry[] table就是哈希桶,Entry类是链表结构

put(key, value)做了什么?

HashMap 刚完成初始化的时候并没有初始化默认的16个哈希桶,只包含一个空的哈希桶数组。第一次执行put方法时会inflateTable,将哈希桶的容量扩充为初始容量向上取整为2的幂,如果你设定初始化容量为17,在这一步会把17变成32。

Map中有transient关键字。 实现Serilizable接口的类,将不需要序列化的属性前添加关键字transient,这个属性就不会序列化。

2. HashMap 初始容量

初始容量为 1 << 4 (16), 且设定初始容量必须是2的幂,这个容量就是HashMap中哈希桶的个数。

为什么初始容量必须是2的幂?

任意一个对象的hashCode的范围是 -2 ^ 31 ~ 2 ^ 31 - 1, 大约是42亿个数。如何将这些数分散放到 n 个哈希桶中?如果使用 i % n 这种算法,有两个缺点:1. 负数求余是负数 ( -1 % 2 = -1) 2. 效率较慢 (硬件中求余的本质是不停的做除法,慢于位运算)

根据哈希值求索引的方法是 hash & (length - 1),如果length是2的幂,

length - 1 的二进制就会是一个全 1 的数,它和哈希值按位与,可以快速的得到一个0 ~ length - 1的数组下标, 且分布是均匀的。

3. 哈希算法

HashMap中的hash(Object o)会对Object的hashCode做再一次的哈希稀疏,减少碰撞,但是java8将java7中的hash(Object o)丢弃了,换成了高16位按位与低16位。

5. 扩容:低效、线程不安全

负载因子默认是0.75

java7的扩容是所有问题的根源。当填入的元素数量大于等于capacity * load factor(容量乘负载因子)时,发生扩容,新的容量是旧的2倍,依然是2的幂。

非常容易碰到死锁问题,在多线程的环境下哈希桶中的链表形成了环,导致cpu100%

https://coolshell.cn/articles/9606.html

潜在的安全隐患

在旧版本tomcat服务器中,get请求的参数使用HashMap保存。精心设计的一系列参数,他们的哈希值都是相同的,会使HashMap退化成链表,引发DoS

6.Java8中的改进

1.由数组+链表变成了数组+链表+红黑树

哈希桶中的元素超过8的时候,哈希桶中的链表会变成红黑树。

2.扩容时插入顺序的改进

最后

以上就是懵懂果汁为你收集整理的java hashmap优势,谈谈 HashMap的全部内容,希望文章能够帮你解决java hashmap优势,谈谈 HashMap所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部