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的主要内容,如果未能解决你的问题,请参考以下文章