HashMap<KV>源码详解

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());
	}
}

 

识别二维码关注个人微信公众号

本章完结,待续,欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值