package java.util;
import java.io.*;
/**
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*
* @author Doug Lea
* @author Josh Bloch
* @author Arthur van Hoff
* @author Neal Gafter
* @see Object#hashCode()
* @see Collection
* @see Map
* @see TreeMap
* @see Hashtable
* @since 1.2
*/
/**
* 1、为什么加载因子越大,HashMap的查询效率越慢?
* 加载因子越大,发生碰撞的可能性越大。
*
*
* 2、Map m = Collections.synchronizeMap(hashMap)
* 3、HashMap的迭代器(Iterator)是fail-fast迭代器
*
*
*/
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{
//位移算法(1的二进制向左移动4位) 0000 0001 ——> 0001 0000 就是结果16
//初始容量
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//最大容量(哈希数组的最大值)
static final int MAXIMUM_CAPACITY = 1 << 30;
//初始加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//Map接口里有一个内部接口Entry<K,V>
//它是Map存放key-value映射的数据结构
static final Entry<?,?>[] EMPTY_TABLE = {
};
//Entry数组(哈希数组),每一个Entry的数据结构就是一个单向链表
//transient关键字表明该对象不会被序列化
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
//键值对的数量
transient int size;
//临界值
//threshold = capacity * loadFactor;
int threshold;
//加载因子
final float loadFactor;
//记录Hashmap被修改的次数
transient int modCount;
//本地修改默认临界值
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
//?????
private static class Holder {
static final int ALTERNATIVE_HASHING_THRESHOLD;
static {
String altThreshold = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"jdk.map.althashing.threshold"));
int threshold;
try {
threshold = (null != altThreshold)
? Integer.parseInt(altThreshold)
: ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
// disable alternative hashing if -1
if (threshold == -1) {
threshold = Integer.MAX_VALUE;
}
if (threshold < 0) {
throw new IllegalArgumentException("value must be positive integer.");
}
} catch(IllegalArgumentException failed) {
throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
}
ALTERNATIVE_HASHING_THRESHOLD = threshold;
}
}
transient int hashSeed = 0;
//构造函数*******
//参数:容量、加载因子
//当容量小于0、加载因子小于0或不是一个数字时会报非法参数异常
//当容量大于最大容量时,则容量等于最大容量
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
//?????
init();
}
//构造函数
//参数:容量
//加载因子为默认加载因子(0.75f)
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
//默认构造函数
//容量为默认初始容量(16)
//加载因子为默认加载因子(0.75f)
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
//构造函数
//参数:Map<? extends K, ? extends V>
public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
//初始化HashMap属性
inflateTable(threshold);
//把参数Map添加进当前Map中
putAllForCreate(m);
}
//Integer.highestOneBit(number)
//取number这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果
private static int roundUpToPowerOf2(int number) {
//14 13 0000 1101 0001 0000 结果:16
//2 1 0000 0001 0000 0010 结果:2
//32 31 0001 1111 0010 0000 结果:32
return number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}
//初始化当前Map的属性
private void inflateTable(int toSize) {
//根据当前临界值上浮得到新的容量
int capacity = roundUpToPowerOf2(toSize);
//根据新的容量重新计算临界值
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
//初始化table(为空)
table = new Entry[capacity];
//初始化hashSeed为0???
initHashSeedAsNeeded(capacity);
}
//?????
void init() {
}
//初始化hashSeed?????
final boolean initHashSeedAsNeeded(int capacity) {
boolean currentAltHashing = hashSeed != 0;
boolean useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean switching = currentAltHashing ^ useAltHashing;
if (switching) {
hashSeed = useAltHashing
? sun.misc.Hashing.randomHashSeed(this)
: 0;
}
return switching;
}
//该方法主要是将Object转换成一个整型,配合indexFor方法找到在数组中的下标位置
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
//stringHash32():Java实现的哈希算法
return sun.misc.Hashing.stringHash32((String) k);
}
//对key的hashCode进行扰动计算
//当两个hashcode高位不同低位相同时会发生碰撞
//扰动计算就是使这两个hashcode运算后低位不同
//^:位异或运算 101和100结果为101
h ^= k.hashCode();
//>>>:无符号右移
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
//对HashMap的容量进行取模(取余)确定数组下标
//位与计算
static int indexFor(int h, int length) {
//&:按位与计算
//h % 2^n = h & (2^n – 1)
return h & (length-1);
}
//获取HashMap的大小
public int size() {
return size;
}
//判断HashMap是不是空
public boolean isEmpty() {
return size == 0;
}
//根据key值获取value
public V get(Object key) {
if (key == null)
return getForNullKey();
//根据key值获取当前HashMap中的Entry<K,V>
Entry<K,V> entry = getEntry(key);
//entry.getValue():Map接口中的方法
return null == entry ? null : entry.getValue();
}
//获取key值为null的value值
private V getForNullKey()
jdk7下HashMap源码分析
最新推荐文章于 2021-03-15 11:59:38 发布