JDK7和JDK8中HashMap的实现

∥☆過路亽.° 提交于 2020-08-09 12:47:27

JDK1.7和JDK1.8中HashMap的实现:

HashMap在JDK1.7之中是使用的 数组 + 链表 的方式来实现数据的存储,当发生Hash值冲突时则在对应节点以链表的形式存储。

JDK1.7中的HashMap

HashMap的底层维护着一个数组,数组中的每一个项都是一个Entry(这个Entry其实就是一个键值对)

Transient Entry<K,V> [] table;

我们向HashMap中存放的对象实际上是存储在该数组中。而Map中的key,value则是以Entry的形式存放在数组中。

static class Entry<K,V> implements Map.Entry<K,V>{
     final K key;   //一个键只能具有一个值,后面的值会被最新的值覆盖
     V value;       //value可以被覆盖
     Entry<K,V> next;  //链表数组 对应数组位置的链表,如果Hash值相同则以链表形式存储
     int hash;      //哈希函数
}

总结map.put后的过程:

当向 HashMap中 put一对键值对 时,它会根据 key的HashCode值计算出一个位置,该位置就是此对象在数组中存放的位置。

如果该位置没有对象存在,则直接将该对象放进数组中;如果有对象,则顺着该对象的链表一直找(有对象进行寻找的作用是在于 Map不允许键值对重复),如果此链有对象的话,则使用equals方法进行比较,若都为false则将put的对象放到数组的链表中的第一位(头位),之前旧的对象链到这个新对象的后面。

——在JDK1.7中HashMap对于数据的存储形式,如果出现成千上万个Hash值碰撞,并且都是在同一个节点的链表中,这个时候HashMap的效率就会大大受到影响,时间复杂度变为O(n);这个问题在JDK1.8中就解决了。

JDK1.8中的HashMap

HashMap在JDK1.8之中的实现则是——使用 位桶 + 链表/红黑树 的方式来实现数据的存储,也是线程不安全的,当某个位桶的链表长度达到某个阈值的时候,就会将链表转换为红黑树的形式存储。

JDK1.8中,当某个桶位的链表节点 不小于8时,将不再以单链表的形式存储对象,而是调整为一颗红黑树——这就是JDK1.7和JDK1.8中HashMap的最大区别。

 

 

Map集合中具有两个实现类:HashTable,HashMap

HashTable是随着Java诞生至今的,具有Synchronized关键字,是线程安全的但效率低;而HashMap则是JDK1.2之后出现的,不具有Synchronized关键字,所以线程不安全但效率高;

场景选择:一般情况下若不是多线程建议使用HashMap效率高;若是涉及多线程时为了保证线程安全建议使用HashTable;(但实际开发中大多数都是单线程的情况,所以一般都是使用HashMap)

(要知道在JDK1.7和1.8之间HashMap之间的实现,我们首先要知道HashMap是什么)

HashMap是什么?

HashTable和HashMap是一种数据结构,称之为 —— 散列表,为什么两者都是呢?因为两个只是线程安全与不安全的差别罢了,底层的功能其实大致上是一致的,只不过现在用HashMap居多,所以面试会多问HashMap在JDK不同版本的一个实现差别。

 HashMap底层实现的主干是数组,但是它的查询、修改、删除、添加等操作,在效率上比 数组、链表等数据结构快!

为什么它这么快?——它主要是通过:关键码值(Key Value)来直接进行访问的数据机构。具体过程就是:通过将关键码值映射到表中的某一个位置来访问记录,这个映射过程中是通过代码进行计算得到的具体位置。

这个映射函数散列函数 / Hash函数,存放记录的数组散列表

Hash函数会出现相同的情况,也就是不同的两个值通过哈希运算后得到了相同的存储地址——哈希碰撞问题

如何解决哈希碰撞问题?——HashMap则是采用了链地址法。具体就是如果发生哈希碰撞问题,就会在对应节点以链表的形式存储。

所以可以衍生出HashMap的原理:数组+链表。 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!