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. MDK下调试时提示AXF文件无法导入的解决方法(转)

    源:http://blog.163.com/zhaojun_xf/blog/static/3005058020117784643555/ 在开发ARM项目中,很多工程师都不太喜欢使用MDK的调试模式, ...

  2. C#入门经典第四章-流程控制-1

    布尔类型:

  3. new关键字的理解-问题型

    //输出的结果是?????????//The answer is good and gbc public class Example { String str=new String("goo ...

  4. CocoaPods安装和使用及问题----看过写的最好的

    目录 CocoaPods是什么? 如何下载和安装CocoaPods? 如何使用CocoaPods? 场景1:利用CocoaPods,在项目中导入AFNetworking类库 场景2:如何正确编译运行一 ...

  5. audio,video标签

    <html><head lang="en"> <meta charset="UTF-8"> <title>< ...

  6. ListView下拉刷新、上拉载入更多之封装改进

    在Android中ListView下拉刷新.上拉载入更多示例一文中,Maxwin兄给出的控件比较强大,前面有详细介绍,但是有个不足就是,里面使用了一些资源文件,包括图片,String,layout,这 ...

  7. didMoveToSuperView 引发的思考

    1. - (void)didMoveToSuperview 通知视图已经移动到一个新的父视图中 2. /**系统自动调用(留给子类去实现)**/ - (void)didAddSubview:(UIVi ...

  8. Oracle教程-查询(二)

    emp 雇员表字段名称   数据类型       是否为空   备注--------   -----------   --------   --------EMPNO    NUMBER(4)     ...

  9. [数据结构]Splay简介

    Splay树,又叫伸展树,可以实现快速分裂合并一个序列,几乎可以完成平衡树的所有操作.其中最重要的操作是将指定节点伸展到指定位置, 目录 节点定义 旋转操作 伸展操作 插入操作 删除操作 lower_ ...

  10. 请问如何在PS中将一张图标里的各个小图标分离成一个个图标?

    1.用切片工具比较简单快捷,把要切的图标一个个的切画出来,切好后存储保存格式为web,导出时候会出现一个images文件里面就是刚切好的图片 2.用裁剪的方式裁剪你要小图标,(你可以记住第一个裁剪的长 ...