1. 链表解决冲突的方式:
 
java中处理Hash散列后的冲突使用的是链表法:
    java8之前只是使用的简单Entry链表存储键值对。java8后,在Entry队列的长度大于8之后,会自动将队列转换成红黑树的存储,利用红黑树相对于链表更好的增改查效率来解决在出现较长链表时性能快速降低的问题。
图片来自美团技术团队
 
 
2. resize() 的方式:
    随着hashMap中数据量的增多,槽不够用的时候需要使用resize来增大槽的容量。此时,需要将所有的数据根据hash值重新散列(此处有著名的死循环问题)。
    java7之前,元素的重新散列需要重新使用hashCode 将元素重新散列。但是java8 中使用了一个非常巧妙的设计,使得不需要重新计算散列值可以快速得出在新表中的位置。原理如下:
    我们槽的容量cap是2的n-1次方,每次扩容都是在原来容量的大小上*2。也就是oldCap < 1。
    而散列的计算方式为(cap-1 & hash), 即hash的低n-1位。
    因此,新的散列位置相对于老的散列位置来说。只是扩容后第n位会对散列结果造成的影响。
    hash值的第n位有两种情况:
        1) hash值的第n位为0,则散列的位置不会变, 
        2) hash值的第n为为1,则散列结果增加了2的(n-1)次方,即oldCap + 原来的散列值。
 
        比如
        初始容量为2,即二进制10;
        有hash值为 1,2, 5, 6 的四个数。根据(cap-1 & hash),他们的散列位置分别为:
                           1,0, 1, 0
        扩容为4,即二进制100后,hash值第2位为1的散列位置加2(如2,6),为0的不变(如1, 5):
                           1,2, 1, 2
    代码如下:
                        Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}

  

 
 
 
 
 
 
 

JAVA8 HashMap 新特性的更多相关文章

  1. java8的新特性以及用法简介

    1. 介绍 2 接口的默认方法 2 lambda表达式 2.1 函数式接口 2.2 方法与构造函数引用 2.3 访问局部变量 2.4 访问对象字段与静态变量 3. 内建函数式接口 3.1 Predic ...

  2. 简单了解JAVA8的新特性

    JAVA8新特性会颠覆整个JAVA程序员的编程习惯 甚至如果您坚守JAVA7之前的编程习惯,今后你看比较年轻的程序员写的JAVA代码都会无法理解 所以为了保证不脱钩,我觉得有必要学习JAVA8的新特性 ...

  3. Java8常用新特性实践

    前言: 时下Oracle开速迭代的Java社区以即将推出Java10,但尴尬的是不少小中企业仍使用JDK7甚至JDK6开发. 从上面列出的JDK8特性中我们可以发现Java8的部分特性很明显的是从Sc ...

  4. Java8 Stream新特性详解及实战

    Java8 Stream新特性详解及实战 背景介绍 在阅读Spring Boot源代码时,发现Java 8的新特性已经被广泛使用,如果再不学习Java8的新特性并灵活应用,你可能真的要out了.为此, ...

  5. java5、java6、java7、java8的新特性

    Java5: 1.泛型 Generics:        引用泛型之后,允许指定集合里元素的类型,免去了强制类型转换,并且能在编译时刻进行类型检查的好处. Parameterized Type作为参数 ...

  6. Java8的新特性以及与C#的比较

    函数式接口 VS 委托 在C中,可以使用函数指针来存储函数的入口,从而使得函数可以像变量一样赋值.传递和存储,使得函数的调用变得十分灵活,是实现函数回调的基础.然而函数指针不存在函数的签名信息,甚至可 ...

  7. Java8部分新特性的学习

    Java8中的新特性 一.Lambda表达式 Lambda表达式可以理解为一种可传递的匿名函数:它没有名称,但又参数列表.函数主体.返回类型,可能还有一个可以抛出的异常列表. 匿名:和匿名类类似的,它 ...

  8. java7与java8的新特性

    java7 新特性: 1. switch 里面的 case 条件可以使用字符串了. 2. 运用 List\tempList = new ArrayList<>(); 即泛型实例化类型自动判 ...

  9. Java8接口新特性

    概述 Java 8中,你可以为接口添加静态方法和默认方法.从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念.猜想设计初衷可能使为了兼容8以下的jdk Java8出来了个函数 ...

随机推荐

  1. PAT (Advanced Level) 1096. Consecutive Factors (20)

    如果是素数直接输出1与素数,否则枚举长度和起始数即可. #include<cstdio> #include<cstring> #include<cmath> #in ...

  2. 困扰你的private static final long serialVersionUID

    很多时候一个新手在写代码的时候,往往你的IDE就会告诉你一个警告 然后你点击处理这个警告之后,它就会默认给你的类生成一个 private static final long serialVersion ...

  3. Django源码解析

    http://www.cnblogs.com/pythoner/archive/2011/07/30/2121599.html

  4. Ubuntu Linux系统下apt-get命令详解

    整理了Ubuntu Linux操作系统下apt-get命令的详细说明,分享给大家.常用的APT命令参数: apt-cache search package 搜索包 apt-cache show pac ...

  5. SystemClock.sleep和Thread.sleep的区别

    在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实 Android平台还提供了一个SystemClock.sleep方 ...

  6. java在CMD环境下执行需注意字符集设定

    最近有个小工具需要将DMS系统中随机文件名替换为原始文件名,当导出原始文件名到csv文件中,用小 工具读取然后rename时,发现在eclipse环境下运行正常,简繁中文名称也正常:但放到cmd中执行 ...

  7. BroadcastReceiver的两种注册方式之------动态注册

    activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...

  8. Python3基础 list() 将一个字符串转换成列表

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  9. GB2312 编码

    GB2312编码范围:A1A1-FEFE,其中汉字编码范围:B0A1-F7FE. GB2312编码是第一个汉字编码国家标准,由中国国家标准总局1980年发布,1981年5月1日开始使用.GB2312编 ...

  10. 猪八戒吃西瓜(wmelon)

    猪八戒吃西瓜(wmelon) 题目描述 有一天,贪吃的猪八戒来到了一个大果园,果园里有n(n≤100000)个大西瓜,每个西瓜 的质量不大于长整型(longint),并且每个西瓜的质量都不同.猪八戒非 ...