HashMap源码剖析(jdk 1.7)
- ***remove方法***
- 1.代码流程解析:
- 1.remove:进入remove方法
- 1.1:去调用了removeEntryForKey方法,得到返回值是当前要删除的value的next的value(也就是当前要删除所在链表值链接的下一个value)。
- 1.2:判断返回值是否为null,为null则直接返回,否则 返回Entry的value。
- 2.removeEntryForKey:进入removeEntryForKey方法
- 2.1:判断当前HashMap是不是空的,如果里面一个值都没有(也就是size == 0),则直接返回null。
- 2.2:通过HashMap的hash算法获取key的hash值。
- 2.3:通过hash值和HashMap的数组长度得到所在数组位置。
- 2.4:声明两个变量最开始都等于当前链表第一位Entry对象,并在while循环中最终得到值为prev=当前循环next的上一个值,e始终=next,除非此链表只有一个值时,prev会等于e。
- 2.5:while循环判断当前链表值是否就是你传入的key值,如果不是则继续往下找并且把perv=当前循环next的上一个值,e始终=next,如果第一个就是当前要找的key,则直接退出返回e出去。
- 2.示例:
- 1.当前有HashMap数据长度为10,示例key值为:
- 2.现在要对 'a2' 进行 remove 掉
- 3.代码流程剖析:
- 3.1:传入'a2',进入removeEntryForKey方法。
- 3.2:得到hash,得到数组下标 i=0。
- 3.3:赋值prev=a的Entry对象(因为链表,得到的对象是数组第一个对象),e=a的Entry对象。
- 3.4:进入循环。
- 3.5:第一次循环,next=e.next=a1的Entry对象,if条件不满足,prev=e=a.Entry对象,e=next=a1的Entry对象。
- 3.6:第二次循环,next=e.next=a1.next=a2的Entry对象,if条件进入,modCount++(增加修改次数),size--(因为要remove,需要把HashMap总长度-1),判断prev==e(判断是否第一次循环),进行remove元素,return掉e (e当前等于a2的Entry对象)。
- 3.源码及注释描述:
大背景:HashMap底层是数组存储数据,通过链表解决hash冲突
remove方法
1.代码流程解析:
1.remove:进入remove方法
1.1:去调用了removeEntryForKey方法,得到返回值是当前要删除的value的next的value(也就是当前要删除所在链表值链接的下一个value)。
1.2:判断返回值是否为null,为null则直接返回,否则 返回Entry的value。
2.removeEntryForKey:进入removeEntryForKey方法
2.1:判断当前HashMap是不是空的,如果里面一个值都没有(也就是size == 0),则直接返回null。
2.2:通过HashMap的hash算法获取key的hash值。
2.3:通过hash值和HashMap的数组长度得到所在数组位置。
2.4:声明两个变量最开始都等于当前链表第一位Entry对象,并在while循环中最终得到值为prev=当前循环next的上一个值,e始终=next,除非此链表只有一个值时,prev会等于e。
2.5:while循环判断当前链表值是否就是你传入的key值,如果不是则继续往下找并且把perv=当前循环next的上一个值,e始终=next,如果第一个就是当前要找的key,则直接退出返回e出去。
2.示例:
1.当前有HashMap数据长度为10,示例key值为:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
[a] [b] [c] [d] [e] [f] [g] [h] [i] [j]
[a1] [b] [c] [d] [e] [f] [g] [h] [i] [j]
[a2]
[a3]
2.现在要对 ‘a2’ 进行 remove 掉
3.代码流程剖析:
3.1:传入’a2’,进入removeEntryForKey方法。
3.2:得到hash,得到数组下标 i=0。
3.3:赋值prev=a的Entry对象(因为链表,得到的对象是数组第一个对象),e=a的Entry对象。
3.4:进入循环。
3.5:第一次循环,next=e.next=a1的Entry对象,if条件不满足,prev=e=a.Entry对象,e=next=a1的Entry对象。
3.6:第二次循环,next=e.next=a1.next=a2的Entry对象,if条件进入,modCount++(增加修改次数),size–(因为要remove,需要把HashMap总长度-1),判断prev==e(判断是否第一次循环),进行remove元素,return掉e (e当前等于a2的Entry对象)。
3.源码及注释描述:
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);// 调用removeEntryForKey方法
return (e == null ? null : e.value);// 判断返回值是否为null,为null直接返回null,否则返回Entry对象的value(也就是平常的key对应的value),这里返回的value就是你要删除的key的value
}
final Entry<K,V> removeEntryForKey(Object key) {
if (size == 0) {// 判断当前HashMap是否没有值,如果没有值则直接返回null
return null;
}
int hash = (key == null) ? 0 : hash(key);// 通过key得到hash值
int i = indexFor(hash, table.length);// 得到hash值所在HashMap的数组下标
Entry<K,V> prev = table[i];// 数组下标拿到Entry对象
Entry<K,V> e = prev;// 变量赋值-此值就是要删除的元素对象
while (e != null) {// 循环链表
Entry<K,V> next = e.next;// 赋值当前链表对象的next到一个变量(比如链表为1,2,3:第一次循环next则=2)
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {// 判断链表中的key是不是你传参的key
modCount++;// 修改次数增加
size--;// 因为要做删除元素操作,要对HashMap的长度-1
if (prev == e)// 判断是否第一次进入
table[i] = next;// 如果是第一次进入,那么要删除的是第一个元素,则把链表位置指向下一个为第一个
else
prev.next = next;// 不是第一次进入,那么把链表链接到要删除元素的上一个Entry的next中,达到链表不间断
e.recordRemoval(this);// 删除元素
return e;// 返回被删除的Entry对象
}
prev = e;// 赋值为当前链表循环next对象的上一个Entry
e = next;// 指向e向下链表探寻
}
return e;// 返回被删除的Entry对象
}
后续方法待补充噢~