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. Python -- Web -- WSGI

    WSGI:Web Server Gateway Interface 只要求Web开发者实现一个函数,就可以响应HTTP请求. # hello.py def application(environ, s ...

  2. 转:Loadrunner学习知多少--脚本录制下载操作

    在很多时候我们可能需要对系统进行这样的脚本开发,模拟用户点击一个下载链接,然后弹出下载框,选择保存,用来测试在大量用户下载时服务器的性能.但是现在大家对于这种脚本的处理方式往往是通过关联和C 语言的文 ...

  3. 使用过滤器(Filter)解决请求参数中文乱码问题(复杂方式)

    前述:      在写这篇笔记之前,对笔记中的设计模式进行介绍:      本篇笔记中将要使用到的设计模式是:装饰(包装)设计模式           (1)装饰(包装)设计模式口诀:         ...

  4. call_grant_exec.sql

    set echo off feedback off verify off pagesize 0 linesize 120 define v_grantee                 = & ...

  5. 客户调查(client)

    客户调查(client) 题目描述 公司派你去和几位客户面谈,以了解他们对公司产品的意见.你逐个打电话与客户联系,得知他们一般都很忙,不过他们还是可以为你抽出一点时间.现在的问题是有些客户的时间有冲突 ...

  6. openwrt串口的使用

    从 RT5350 的芯片手册上可以得知, RT5350 一共有两个串口, 分别为 UART Lite. UART Full, UART Lite 就是我们惯称为的串口 1,作为系统调试串口,通过这个串 ...

  7. mysql安装使用--2 用户管理

    1 修改mysql.user表 添加用户 mysql> INSERT INTO mysql.user (Host,User,Password) VALUES (\'%\',\'system\', ...

  8. JAVA基础-- 对象转型 (casting)

    1. 一个基类的引用类型变量可以指向其子类的对象: a=new Dog("bigyellow","yellow"); 2. 一个基类的引用不可以访问其子类对象新 ...

  9. js原型对象,每个new出来的新对象都有独立的原型对象__proto__

    刚才看一篇博文的时候, 动手测试了一下 JavaScript的原型链, 原型对象,发现每个构造器(赋给了某个 prototype ) new 出来的对象都有各自独立的原型对象 __proto__. p ...

  10. 手动启动Android模拟器

    1.5版本中加了个所谓的AVD(Android Virtual Device),AVD就相当于是一个模拟器的,不过你可以利用AVD创建基于不同版本的模拟器,然后使用emulator-avd avdNa ...