排查思路
- 从报错的关键字中可以大致判断是是key冲突,Duplicate key在数据库的主键冲突错误中经常遇到,个人的思维惯性就联想到了数据库,从这个方向去排查,无果。
- 抓耳挠腮之下,分析如下错误信息
java.lang.IllegalStateException: Duplicate key image(id=1,name='晓明')at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)at java.util.HashMap.merge(HashMap.java:1253)at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
这里是当时的问题代码,本意是想把查出来的文件list再以文件fileId作为Map的key转换成map,结果库里有两个一样的文件ID就导致了错误的发生,因为map的key是唯一的。
Map<String, ImageFile> oldImageFileMap = list(new LambdaQueryWrapper<ImageFile>().eq(ImageFile::getOrderNo, orderNo).eq(ImageFile::getDeleteFlag, 0)).stream().collect(Collectors.toMap(ImageFile::getOriginalFileId, Function.identity()));
以下是源码片段
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper) {return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
public static <T, K, U, M extends Map<K, U>>Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier) {BiConsumer<M, T> accumulator= (map, element) -> map.merge(keyMapper.apply(element),valueMapper.apply(element), mergeFunction);return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);}
private static <T> BinaryOperator<T> throwingMerger {return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
解决方案:
用集合转map的另外的重载方法二
修改后的代码
Map<String, ImageFile> oldImageFileMap = list(new LambdaQueryWrapper<ImageFile>().eq(ImageFile::getOrderNo, orderNo).eq(ImageFile::getDeleteFlag, 0)).stream().collect(Collectors.toMap(ImageFile::getOriginalFileId, Function.identity(),(v1,v2)->v2));