jdk源码hashMap的1.7与1.8的比较

1.8链表的定义基本上与1.7相同,但是类名改为Node,但是node实现了Map.Entry接口,实质是一样的

static class Node<K,V> implements Map.Entry<K,V> {

1.8的hash值的算法更加直观一点,就是key的hashcode与无符号右移16位的hashcode异或,然后返回。这是为了当length比较小的时候,也能保证考虑到高低Bit位都参与到Hash的计算中,同时不会有太大的开销。

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

tableSizeFor主要功能是返回一个比给定整数大且最接近的2的幂次方整数,返回的是n+1,实例如下,右移一位,把最高位的1后面一位也变成了1,通过右移,把最高位后面全部置换成1,最后n+1,即为最接近传入数的2的幂次方整数

static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

hashmap1.8的数据结构如下,当链表的长度不小超过8的话就按链表存储,若是超过了8,那么通过treeifyBin 转化为红黑树

final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; Node<K,V> e;
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize();
        else if ((e = tab[index = (n - 1) & hash]) != null) {
            TreeNode<K,V> hd = null, tl = null;
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);//把每个及节点转化为TreeNode
                if (tl == null)
                    hd = p;
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
            if ((tab[index] = hd) != null)
                hd.treeify(tab);
        }
    }

TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
        return new TreeNode<>(p.hash, p.key, p.value, next);
    }

原文地址:https://www.cnblogs.com/wanglingdeboke/p/9713731.html

时间: 2024-08-03 03:21:53

jdk源码hashMap的1.7与1.8的比较的相关文章

JDK源码-HashMap

1,Map:映射表数据结构,通过key-value完成映射.HashMap的子实现主要包括:HashMap.LinkedHashMap.TreeMap.WeakHashMap.ConcurrentHashMap.IdentityHashMap.以下总结摘录自<Thingking In Java> -1,HashMap:使用Map集合的默认选择.因为HashMap对速度进行了优化.HashMap是Map基于散列表的实现,并取代了Hashtable.插入和查询的效率相对固定.可以通过构造器设置容量

jdk源码——HashMap

JDK1.7 从源码上看,HashMap 实现了Map接口 cloneable接口,和序列化接口 public class HashMap<K,V>    extends AbstractMap<K,V>    implements Map<K,V>, Cloneable, Serializable{ HashMap的默认初始容量为16 static final int DEFAULT_INITIAL_CAPACITY = 16; HashMap最大容量为2^30 st

JDK源码--HashMap(之resize)

1.HashMap源码阅读目标了解具体的数据结构(hash及冲突链表.红黑树)和重要方法的具体实现(hashCode.equals.put.resize...) 2.重要方法 hashCode 与 equals都是在AbstractMap中定义的 hashCode是各元素hash的累加 h += iter.next().hashCode(); equals 1.是否是本身; 2.是否是Map实例; 3.size是否相等; 4.比较每个value 重点在于put.resize具体实现步骤: put

由JDK源码学习HashMap

HashMap基于hash表的Map接口实现,它实现了Map接口中的所有操作.HashMap允许存储null键和null值.这是它与Hashtable的区别之一(另外一个区别是Hashtable是线程安全的).另外,HashMap中的键值对是无序的.下面,我们从HashMap的源代码来分析HashMap的实现,以下使用的是Jdk1.7.0_51. 一.HashMap的存储实现 HashMap底层采用的是数组和链表这两种数据结构.当我们把key-value对put到HashMap时,系统会根据ha

【图解JDK源码】HashMap的基本原理与它的线程安全性

1. 前言 能用图说清楚的,就坚决不用代码.能用代码撸清楚的,就坚决不写解释(不是不写注释哦). 以下所有仅针对JDK 1.7及之前中的HashMap. 2. 数据结构 HashMap内部通过维护一个Entry<K, V>数组(变量为table),来实现其基本功能,而Entry<K, V>是HashMap的内部类,其主要作用便是存储键值对,其数据结构大致如下图所示. 从Entry的数据结构可以看出,多个Entry是可以形成一个单向链表的,HashMap中维护的Entry<K,

jdk源码阅读-HashMap

前置阅读: jdk源码阅读-Map : http://www.cnblogs.com/ccode/p/4645683.html 在前置阅读的文章里,已经提到HashMap是基于Hash表实现的,所以在讲解HashMap之前 ,有必要提前了解下Hash的原理. 参考<算法导论><算法>

JDK源码笔记-java.util.HashMap

HashMap 的存储实现 当程序试图将多个 key-value 放入 HashMap 中时,以如下代码片段为例: Java代码 HashMap<String , Double> map = new HashMap<String , Double>(); map.put("语文" , 80.0); map.put("数学" , 89.0); map.put("英语" , 78.2); HashMap 采用一种所谓的&quo

【图解JDK源码】HashMap的容量大小增长原理(JDK1.6/1.7/1.8)

1. 前言 HashMap的容量大小会根据其存储数据的数量多少而自动扩充,即当HashMap存储数据的数量到达一个阈值(threshold)时,再往里面增加数据,便可能会扩充HashMap的容量. 可能? 事实上,由于JDK版本的不同,其阈值(threshold)的默认大小也变得不同(主要是计算公式的改变),甚至连判断条件也变得不一样,所以如果说threshold = capacity * loadFactor(容量 * 负载因子)将不再绝对正确,甚至说超过阈值容量就会增长也不再绝对正确,下面就

阅读JDK源码有感

最近加班不是很严重,爱上了查看JDK源码,每天回来,准备一杯咖啡,开始阅读,受益良多.从上周开始阅读,觉得还是写下感想和学习心得比较好.以后每天阅读,每天记下收获.总体来说,我觉得JDK源码写得十分漂亮,无论是从代码风格还是从重用性来说,都是相当出色的.之前阅读过Thinking in java,感觉很多东西都不能深入理解,太过于理论化,现在结合JDK看来,又别有一番感悟.以前每次有面试,都会从网上收集一些面试题,死记硬背一些知识,HashMap与HashTable的区别啊之类的,但是看了JDK