HashMap源码剖析(jdk 1.7)

HashMap源码剖析(jdk 1.7)

大背景: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对象
}

后续方法待补充噢~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值