如何更新ConcurrentHashMap并返回更新前的原有值
方案1:使用getAndPut直接实现需求(最简洁高效)
你的需求是固定将对应键的值设为0、返回更新前的旧值,完全可以用ConcurrentHashMap自带的原子getAndPut方法实现,不需要用到compute,代码如下:
public static long zeroValue(String mapKey) { Long oldVal = concurrentMap.getAndPut(mapKey, 0L); // 处理键原本不存在的场景,返回默认0,可根据业务调整默认值 return oldVal == null ? 0L : oldVal; }
getAndPut是原子操作,会返回设置之前的旧值,完全满足你的需求,性能比compute更高。
方案2:解决lambda表达式无法修改外部局部变量的通用方法
如果你后续有更复杂的计算逻辑必须用compute,可以用单元素数组或者原子容器来中转旧值,利用数组/容器本身引用是终态、内部元素可修改的特性绕开语法限制:
用单元素数组实现:
public static long zeroValue(String mapKey) { final long[] oldVal = new long[1]; concurrentMap.compute(mapKey, (key, val) -> { oldVal[0] = val == null ? 0L : val; return 0L; }); return oldVal[0]; }
用AtomicLong实现:
public static long zeroValue(String mapKey) { AtomicLong oldVal = new AtomicLong(); concurrentMap.compute(mapKey, (key, val) -> { oldVal.set(val == null ? 0L : val); return 0L; }); return oldVal.get(); }
原代码报错原因说明
Java lambda表达式只能捕获**有效终态(effectively final)**的外部变量,即变量的引用在初始化后不能再修改。你直接声明long ret在lambda中修改,属于修改局部变量的引用,不符合语法要求;而数组/原子容器的引用本身是终态,lambda中修改的是其内部的元素/属性,不会修改引用本身,因此可以正常编译。
内容的提问来源于stack exchange,提问作者MikeKulls
相关产品推荐
相关产品推荐

