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. Django - 用户注册

    使用Django工程自动创建的auth_user表来存储用户信息 在app目录下创建forms.py mysite/music/forms.py from django.contrib.auth.mo ...

  2. Node.js学习 - Route

    Node.js 路由 URL解析,需要url和querystring两个模块url.parse(string).query | url.parse(string).pathname | | | | | ...

  3. Roboguice学习之视图注入

    Robuguide的使用 准备工作: 首先在项目中必须实现GreetingModule和RoboguiceDemoApplication GreetingModule.java import com. ...

  4. PAT (Advanced Level) 1114. Family Property (25)

    简单DFS. #include<cstdio> #include<cstring> #include<cmath> #include<vector> # ...

  5. DedeCMS中实现在顶层banner中显示自定义登录信息

    一.需求描述 dedeCMS自带的模板中有互动中心模块,如下图所示: 由于会员登陆对我来说不是网站的重要模块且默认DedeCMS的会员中心模块的初始化很慢,常会显示“正在载入中,请稍候...”, 所以 ...

  6. 用JavaScript 来将数字转换成字符。

    背景: 一切嵌入式设备上面的信息,比如设备名称,设备时区是可以写入到设备上面的寄存器中的(一个寄存器两个字节,2*8 bit),比如 -1 ,写入到寄存器中为 2d31,然后可以通过一些进程将寄存器中 ...

  7. 基于Verilog HDL 各种实验

    菜鸟做的的小实验链接汇总:           1.基于Verilog HDL 的数字时钟设计 2.乘法器 3.触发器(基本的SR触发器.同步触发器.D触发器) 4.基于Verilog HDL的ADC ...

  8. json转义字符串

    json前台写数据 @RequestMapping("/addUserJson") public void addUserJson(User user,HttpServletReq ...

  9. gridcontrol第一行为0,没有选中为-999999

  10. mac 剪切文件

    首先选中文件,按Command+C复制文件:然后按Command+Option+V:就可以把你的文件剪走了!在这里补充一下,我这里讲的是剪切文件夹,不是剪切文本和文字!Command+X只能剪切文字文 ...