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. Windows、Linux -- 远程登录、文件传输、文件共享

    Linux  <--->  Linux 远程登录: ssh服务 ssh root@10.20.62.124 文件传输: scp服务 上传  scp /home/xxx.txt root@1 ...

  2. IP地址、子网掩码详解

    如何通过子网掩码划分网段 资料一: 一.缺省A.B.C类地址,子网掩码:  二.子网掩码的作用:  code:  IP地址 192.20.15.5 11000000 00010100 00001111 ...

  3. Junit单元测试的简单使用(主要是在spring框架下的项目)

    首先是解释什么是单元测试,单元测试是指对于一个大型项目里,对于单一模块或者单一接口的测试. 然后解释为什么要写单元测试,首先对于一个大型的项目,如果你每次都要重启一遍服务器调页面或者接口的bug,那就 ...

  4. struts2 里escape="false"的问题?

    <s:property value="html" escape="false"/> 没有name 不知道你是怎么取的值 <s:hidden n ...

  5. iomanip头

    #include <iomanip>主要是输入输出控制. Dec 十进制: hex 十六进制: oct 八进制: setw 设置宽度: setfill 设置填充值: setbase 将数字 ...

  6. zencart 具体页面调用规则: $body_code变量解析

    zencart $body_code变量解析 修改centerColumn 可以修改中间产品方框的大小 2.2.5 .BODY文件在这个文件生效 require($body_code) include ...

  7. Zencart 500错误查找和解决方法

    有时在一些虚拟主机下(如HostMonster,BlueHost),Zencart网站会莫名奇妙输出空白页面,查看HTTP头,其实可以看到是500错误.至于500错误的出现原因,一般是由于服务器脚本或 ...

  8. oracle 日期相减

    oracle日期相减2012-02-10 12:18--MONTHS_BETWEEN(date2,date1) 给出date2-date1的月份 SQL> select months_betwe ...

  9. CSS盒模型和margin重叠

    在 CSS 中,width 和 height 指的是内容区域的宽度和高度.增加内边距.边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸.(div的实际占用尺寸变打了) 但: 一旦为页面设置 ...

  10. iOS图片缓存框架SDWebImage

    本文转发至: http://blog.csdn.net/uxyheaven/article/details/7909373 http://www.cocoachina.com/ios/20141212 ...