HashMap evict 放逐之旅

HashMap evict 放逐之旅

我不认识的evict

正在撸猫写代码的我,遇到了一个LinkedHashMap ConcurrentModifyException,真是让人头秃。问题排查过程也是费了一些力气(手动狗头),最后发现是我异步请求接口时,同步修改了同一个map,所以主流程代码在读这个map的时候,会偶发性的出现ConcurrentModifyException(如果有人感兴趣排查过程,评论区留言,后续更贴)。
就在我在解决这个问题的时候,就遇到了Map深复制这个情况,我需要copy一份map用于异步请求的时候用。智能的Intellij 告诉我,我可以在初始化的时候传入map,我一直很相信我的得力助手,所以就这样一顿操作,调试运行没有问题,晚上又可以早点下班了。
但深复制这个情况,我还是需要从源码的角度确认一下,就看了LinkedHashMap初始化的代码

public LinkedHashMap(Map<? extends K, ? extends V> m) {
        super();
        accessOrder = false;
        putMapEntries(m, false);
 }

各位看官这个m肯定没有问题,但是这第二个参数传了一个false,给的注释是

evict false when initially constructing this map, else true (relayed to method afterNodeInsertion).

机智的我查了一下这个单词的意思
evict单词解释
evict这个变量当在map初始化的时候是false,其他情况为true,传递给afterNodeInsection方法。

void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            removeNode(hash(key), key, null, false, true);
        }
 }
 
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
}

然后这removeEldestEntry给了一大串注释,我就总结一下:我提供了方式给你重写在添加一个新元素之后删除map中最老的元素。然后作者说了一句话

this is useful if the map represents a cache: it allows the map to reduce memory consumption by deleting stale entries.

对于这个Cache,我搜索了一下,发现LinkedHashMap 可以作为LRU算法实现的数据结构。

LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰

关于LRU算法,看官们可以自行学习了解。

小结

最后总结一下,evict这个变量当在map构造器传入指定map初始化的时候是false,其他情况为true,也即其他构造器创建map之后再调用put方法,该参数则为true。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值