记一次开发中遇到副作用与幂等问题
问题代码:
private final ConcurrentHashMap<String, List<Region>> store = new ConcurrentHashMap<>(); @Override public List<Region> tree(boolean province) { String storeKey = "regions" + province; List<Region> regions = store.computeIfAbsent(storeKey, key -> baseMapper.tree(province)); return ForestNodeMerger.merge(regions); }
引用变量 regions 实际是 store 里保存的值。而 ForestNodeMerger.merge 方法产生副作用,改变了store 的状态。因此该方法不是幂等的。
等价的例子:
private static HashMap<String, List<Integer>> hm = new HashMap<>(); public static void addNumbers() { ArrayList<Integer> list = new ArrayList<>(); list.add(3); list.add(4); list.add(5); List<Integer> list1 = hm.computeIfAbsent("list", key -> list); list1.add(6); System.out.println(list1); } public static void main(String[] args) { addNumbers(); addNumbers(); }
输出结果为:
[3, 4, 5, 6] [3, 4, 5, 6, 6]
解决方法
private final ConcurrentHashMap<String, List<Region>> store = new ConcurrentHashMap<>(); @Override public List<Region> tree(boolean province) { String storeKey = "regions" + province; return store.computeIfAbsent(storeKey, key -> ForestNodeMerger.merge(baseMapper.tree(province))); }
将可能产生副作用的代码合并,只在最开始产生副作用。因此该方法是幂等的。
2333