HashMap

Posted liweibing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap相关的知识,希望对你有一定的参考价值。

HashMap

        实现了 Map<K,V> 接口, HashTable实现了Dictionary<K,V>

        数据结构 : 数组 + 链表 + 红黑树(增加查询速度)

 

        基本使用方法 :

技术图片

 

 

     1 . 从测试用例开始查看HashMap的源码

         当然在查看前 , 我们先来认识几个我们需要知道的成员变量.

         static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;   // 默认初始化可存放元素个数

         static final int MAXIMUM_CAPACITY = 1 << 30;    // 数组内最大存放元素个数

         static final float DEFAULT_LOAD_FACTOR = 0.75f;   //负载因子

         static final int UNTREEIFY_THRESHOLD = 6;    //当链表少于6个的时候, 会再次转为链表

        static final int MIN_TREEIFY_CAPACITY = 64;  // 当一个链表个数达到8,会尝试将其变为红黑树,但是如果这个时候map内元素的总个数 < 64 , 会优先考虑扩容.

  transient Node<K,V>[] table;      // 操作的数组

 

 

 

 技术图片

 

 

 技术图片

 

 

 技术图片

 

 

 a . 直接开始看第三个构造方法.

      1. 首先校验初始化元素个数是否 < 0 ,  true 的话 , 就抛出异常.

      2. 初始化的元素个数是否已经超出了最大值, 如果超出,按最大值来算.

      3. 负载因子是否为 < = 0 或者 不是个Float类型的数字. ( NaN = Not a Number ) , 为true ,抛出异常

      4. 在为 threshold 这个元素赋值的时候, 需要对这个元素重新计算. 要求必须为2的倍数

          当为2的倍数的时候,  key的hash值 % 数组长度 = key的hash值 & (n-1)  . n是数组长度 .

          包括后面扩容时,高位链与低位链的使用.

      技术图片

 

 

  2. 接下来开始看 put 方法.

         技术图片

 

      

        a . 直接调用了 putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) 方法. 我们先来看一下这个方法的4个参数

            1. hash  . 是将key进行hash运算后的结果. 这里我们可以看到 HashMap的 key 和 value都是允许为空的,如果key为null ,默认存储在数组的第一位.

            技术图片

 

 

             2. 这里补充一个点,当数组的Key为一个对象的时候,因为在我们实际的场景中,希望只要对象内属性一样,就默认为同一个.所以我们就需要重写这个对象的 hashCode()方法了.

             3. 这里的key进行hash()计算,不仅仅是进行了一个hashCode(), 因为是int类型, 这个还将计算出来的结果像右移16位,让高位和地位进行了异或,使高位和地位都参与了运算,在位桶内分布更加均匀.

     b. 第二个参数就是value,我们传输的值

     c . Boolean onlyIfAbsent = false .当这个元素为false的时候,默认key相同时,会对value进行覆盖.为true,则保持第一次的value值不变

     d . evict if false, the table is in creation mode. 默认为true

 

   2. 开始看 putVal方法.

 

            源码如下 :

 

   技术图片

 

 技术图片

 

 技术图片

 

技术图片

 

 

a .  首先判断成员变量 Table 是否为Null ,或者当前数组长度为0 , 那么就需要进行扩容(其实这个时候叫初始化比较合适.)

      进入resize()方法

      初始化进入的时候(见下图代码),

     1.  首先将 成员变量数组 table赋值给

     技术图片

 

 技术图片

 

 

 

 

 

 

 

 

 

 

 

 

   

 

以上是关于HashMap的主要内容,如果未能解决你的问题,请参考以下文章

HashMap原理:哈希函数的设计

HashMap深度解析

JDK源码阅读之 HashMap

ArrayList 和 HashMap 的默认大小是多数?

如何将 Parcelable 与 HashMap 一起使用

hashmap冲突的解决方法以及原理分析: