当前位置: 首页 > wzjs >正文

北航做网站公司网站开发商官网

北航做网站公司,网站开发商官网,wordpress网站用户共享,免费追剧JDK1.8之前 JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。 HashMap 通过 key 的 hashcode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度)&a…
JDK1.8之前

JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列
HashMap 通过 key 的 hashcode 经过扰动函数处理过后得到 hash 值,然后通过
(n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

JDK1.7的hash方法源码

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);
}

JDK1.8之后的hash方法源码

    static final int hash(Object key) {int h;// key.hashCode():返回散列值也就是hashcode// ^:按位异或// >>>:无符号右移,忽略符号位,空位都以0补齐return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

JDK 1.7使用更复杂的哈希算法(9次扰动处理),而JDK 1.8简化了哈希算法(1次扰动处理)。此外,JDK 1.7在扩容时先进行扩容再插入新元素,重新计算所有元素的位置,而JDK 1.8则先插入新元素再判断是否需要扩容,优化了重新计算位置的算法‌。
 

Hashmap解决哈希冲突的方法为拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。

jdk1.7数组+链表,1.8之后数据+链表或红黑树

假设我们有一个 HashMap,其桶数组的大小为 16(即有 16 个桶)。以下是一个简单的示意图:

HashMap
+-------------------+
| 0 -> (K1, V1) -> (K2, V2) -> (K3, V3) [Red-Black Tree]
| 1 -> (K4, V4)
| 2 -> (K5, V5) -> (K6, V6) [Red-Black Tree]
| 3 -> null
| 4 -> (K7, V7)
| 5 -> null
| 6 -> (K8, V8) -> (K9, V9)
| 7 -> null
| 8 -> (K10, V10)
| 9 -> null
| 10 -> (K11, V11)
| 11 -> null
| 12 -> (K12, V12)
| 13 -> null
| 14 -> (K13, V13)
| 15 -> null
+-------------------+

     

JDK1.8之后

相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值
(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树。

这样做的目的是减少搜索时间:链表的查询效率为 O(n)(n 是链表的长度),红黑树是一种自平衡二叉搜索树,其查询效率为 O(log n)。当链表较短时,O(n) 和 O(log n) 的性能差异不明显。但当链表变长时,查询性能会显著下降。

为什么优先扩容而非直接转为红黑树

数组扩容能减少哈希冲突的发生概率(即将元素重新分散到新的、更大的数组中),这在多数情况下比直接转换为红黑树更高效。

红黑树需要保持自平衡,维护成本较高。并且,过早引入红黑树反而会增加复杂度。

为什么选择阈值 8 和 64?

  1. 泊松分布表明,链表长度达到 8 的概率极低(小于千万分之一)。在绝大多数情况下,链表长度都不会超过 8。阈值设置为 8,可以保证性能和空间效率的平衡。
  2. 数组长度阈值 64 同样是经过实践验证的经验值。在小数组中扩容成本低,优先扩容可以避免过早引入红黑树。数组大小达到 64 时,冲突概率较高,此时红黑树的性能优势开始显现。

TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构

我们来结合源码分析一下 HashMap 链表到红黑树的转换。

1、 putVal 方法中执行链表转红黑树的判断逻辑。

链表的长度大于 8 的时候,就执行 treeifyBin (转换红黑树)的逻辑。

// 遍历链表
for (int binCount = 0; ; ++binCount) {// 遍历到链表最后一个节点if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);// 如果链表元素个数大于TREEIFY_THRESHOLD(8)if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st// 红黑树转换(并不会直接转换成红黑树)treeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;
}

2、treeifyBin 方法中判断是否真的转换为红黑树。

final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;// 判断当前数组的长度是否小于 64if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)// 如果当前数组的长度小于 64,那么会选择先进行数组扩容resize();else if ((e = tab[index = (n - 1) & hash]) != null) {// 否则才将列表转换为红黑树TreeNode<K,V> hd = null, tl = null;do {TreeNode<K,V> p = replacementTreeNode(e, null);if (tl == null)hd = p;else {p.prev = tl;tl.next = p;}tl = p;} while ((e = e.next) != null);if ((tab[index] = hd) != null)hd.treeify(tab);}
}

将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树。

   

http://www.dtcms.com/wzjs/560012.html

相关文章:

  • 大型网站建设开发百姓网推广电话
  • 别人网站建设多少钱亚马逊电商网站
  • 网站建设先进部门评选标准阳谷网站建设费用
  • 美容北京公司网站建设做外单都有什么网站
  • 腾讯官方网站建设第1 ppt模板网
  • 哪里有网站制作文案策划公司
  • 昆明做企业网站多少钱wordpress 搭建电商
  • 云南大永高速公路建设指挥部网站长沙便宜网站建设
  • 免费cms建站五指深圳品牌网站推广公司
  • 免费样机素材网站互联网百强企业排名
  • 网站建设中图片是什么重庆公司直招
  • 鄱阳网站建设多少钱wordpress改主题
  • wordpress娱乐网成都市seo网站公司
  • 企业官方网站制作推广软件响应式网站建设外文文献
  • 如何建设营销型网站品牌建设归哪个部门管
  • asp.net获取网站虚拟目录设计网站的关键点
  • 罗湖高端网站设计wordpress去底部版权信息
  • 网站首页页面设计模板中国制造网外贸站
  • 廉江网站制作专业的河南网站建设公司哪家好
  • wordpress修改后台管理地址=广州seo网站设计
  • 电商企业网站建设的一般要素有哪些6青浦网站建设su35
  • 二级域名分发网站源码做网站那个好
  • asp程序设计做网站装修图片
  • 夏津网站建设电话网络门店管理系统登录
  • 淮南网站制作公司页游和做网站
  • 有什么建筑网站wordpress 主题制作 视频
  • 宝山宜昌网站建设淘宝客网站哪里可以做
  • qq网站推广代码副国级人员名单
  • 余姚微信网站建设策划书封面
  • 旅游网站网页设计方案网站模版编辑器