HashMap<K,V>源码详解(基于jdk1.8.0_162)
介绍:HashMap<K,V>是一种键值对存储结构。
HashMap<K,V>在jdk1.8之后,底层实现方式变为数组+单链表+红黑树了。
HashMap<K,V>是非线程安全的。
HashMap<K,V>基于哈希法(散列法)实现。
哈希法(散列法)特性:hashCode可能会有相同的情况,相同时称为哈希冲突。所以判断元素是否相同时,需要用hashCode和equals的方式一起判断,两者都返回true,才确定唯一元素。
HashMap<K,V>中的哈希函数:
/*
* 使用h>>>16的方式,运算时效率更高
* ^异或操作主要是为了保证,只要hashCode的32位有一位改变,整个hashCode就会改变,大大减少了哈希冲突
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
一、类图
二、构造方法
1)HashMap()
构造一个空的HashMap,默认初始容量(16)和默认负载系数(0.75)。
2)HashMap(int initialCapacity)
构造一个空的 HashMap,具有指定的初始容量和默认负载系数(0.75)。
3)HashMap(int initialCapacity, float loadFactor)
构造一个空的 HashMap具有指定的初始容量和负载系数。
4)HashMap(Map<? extends K,? extends V> m)
构造一个新的 HashMap与指定的相同的映射Map 。
备注:负载系数是用户当存储内容超过初始容量时,需要进行扩容的计算,比如初始容量是16,负载系数是0.75,当HashMap容量超长16时,需要对HashMap进行扩容,计算方式为:扩容容量=初始容量+初始容量*负载系数。
三)添加
1)put(K key, V value) :添加指定key和value到HashMap中。
2)putAll(Map<? extends K,? extends V> m) :将m的值全部插入到HashMap中。
工作原理:
第一步:先计算key的hashCode,计算方式:(h = key.hashCode()) ^ (h >>> 16)
第二步:计算数组大小,当超过initialCapacity * loadFactor时,需要扩容。
第三步:判断key的hasCode是否存在,如存在,会发生hash冲突,再判断value是否一致,如一致就替换成新的value,如value不一致,插入元素。
第四步:再判断存储方式,如果长度小于8,用数组存储,大于8,转换成红黑树存储。
计算方式说明:使用h>>>16的方式,运算时效率更高,^异或操作主要是为了保证,只要hashCode的32位有一位改变,整个hashCode就会改变,大大减少了哈希冲突。
备注:key的hashCode可能会相同,在相同时,需要再用equals方式比对key是否相同,如两者都返回true,就是true。这是哈希法的一种特性。
四)修改
1)replace(K key, V value) :查找hashCode和key全部相同的节点,替换value,针对于key处理。
2)replace(K key, V oldValue, V newValue) :查找hashCode和key和value全部相同的节点,替换成newValue。
备注:put添加方式也是一种另类的修改,只不过性能会比replace差一些(因为需要判断是否扩容等等)。
五)查找
1)get(Object key) :查找hashCode和key全部相同的节点,并返回。
六)删除
1)remove(Object key) :删除指定的key的条目(hashCode和key全部相同)。
2)remove(Object key, Object value) :只有key和value都匹配时,才删除条目。
七)迭代
1)keySet():返回HashMap所有的key,只需要获取key情况下,可选该方式。
2)entrySet():返回HashMap所有的key和value,推荐使用。
/**
* 获取key列表
*/
public static void keySet() {
HashMap<String, Object> map = new HashMap<String, Object>();
Set<String> set = map.keySet();
for (String key : set) {
System.out.println("key: " + key);
}
}
/**
* 获取key和value列表(推荐使用)
*/
public static void entrySet() {
HashMap<String, Object> map = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}
}
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!