HashMap源码解读
2019-12-05 本文已影响0人
spring_coderman
基于JDK1.7进行源码解读
HashMap类图与方法
HashMap.pngHashMap中的属性
属性.jpg 属性2.jpgHashMap中的构造方法
构造方法1.jpg构造方法2.png
数组初始化.jpg
核心数据结构.jpg
HashMap中的put方法
put方法.jpg创建k-v.jpg
hash计算与数组下标寻找.jpg
空key处理.jpg
HashMap中的get方法
get操作.jpg get操作2.jpg元素判断3.jpg
并发修改和迭代操作
并发修改问题7.jpghashMap的迭代.jpg
删除操作源码(截图不全,走文字描述)
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
* for this key.
*/
final Entry<K,V> removeEntryForKey(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
//计算数组下标后将头结点赋值给前驱结点
Entry<K,V> prev = table[i];
//将前驱结点赋值给临时变量结点e,这个e结点就是要删除的节点
Entry<K,V> e = prev;
//对临时变量结点e进行遍历
while (e != null) {
Entry<K,V> next = e.next;
Object k;
//如果满足if条件则说明找到要删除的节点了
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
//增加修改次数
modCount++;
//将数组大小减1
size--;
if (prev == e)
//如果前驱结点与当前节点一样,就是说链表第一个节点是要删除的数据,直接将
//第一个节点的下一个节点作为链表的第一个节点
table[i] = next;
else
//这里说明链表的第一个节点不是要删除的节点,直接将前驱节点的下一个节点指向到当前节点的下一个节点,就完成了
//删除目标节点的操作
prev.next = next;
//标记这个k-v是删除状态
e.recordRemoval(this);
return e;
}
//没找到就先记录前驱结点为当前阶段
prev = e;
//下一个节点为当前节点
e = next;
}
return e;
}
HashMap中的扩容操作
进行扩容.jpg扩容实现.jpg 序列化与反序列化2.jpg
总结
- 基于jdk1.7实现的HashMap的数据结构就是数组(table)+链表(entry),数组中的元素是是entry链表的头结点.
- HashMap的key-value都可以为空,且对这种情况做了特别的处理
- HashMap存在并发修改和死链问题,大数据量+多线程下不安全,建议使用ConcurrentHashMap
- 扩容的时候链表中的元素会被打乱已有位置和顺序,根据扩容的新的位置进行重新组织数据
- 1.7版本HashMap的源码还是比较少,也稍微好分析的,大概1180行,这里选取比较核心的方法和常用操作进行源码分析。
- 相关链接https://www.jianshu.com/p/4aa3bb16f36c
- 相关链接https://www.cnblogs.com/yangyongjie/p/11015174.html