背景:生产环境有一个批量创建问文件夹的接口,接口逻辑一次传入多个文件夹名称,去发号器批量申请文件夹id
某个场景下前端入参的文件夹名称重复,导致服务端报错如下
代码:
public class MyTest {
public static void main(String[] args) {
List<mydto> mydtoList= new ArrayList<>(2);
mydto a = new mydto();
a.setId(100L);
a.setName("a");
mydto b = new mydto();
b.setId(101L);
b.setName("a");
mydtoList.add(a);
mydtoList.add(b);
Map<String,Long> d =mydtoList.stream().collect(Collectors.toMap(mydto::getName,mydto::getId));
}
}
class mydto {
private String name;
private Long id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 100
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1256)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.fancv.MyTest.main(MyTest.java:21)
神奇的报错信息
jdk 1.8 的报错信息有误导性性, Duplicate key 100,让人容易理解 id重复了,事实上是 name 重复了,可能是幸运女神眷顾,在整个业务场景下爆出这错,团队成员都误认为是id重复了,耽误了半天时间,后边证实是 name重复了
相比之下 jdk 11 的提示信息友好很多
Exception in thread "main" java.lang.IllegalStateException: Duplicate key a (attempted merging values 102 and 101)
at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133)
at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180)
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at com.fancv.MyTest.main(MyTest.java:21)
排查问题的思考
jdk1.8 的报错信息已经定位到具体行数,根据上下文可以推理出不可能id重复,如果是其他业务场景和id没关系,追到这也就可以了
排查问题尽可能的还原现场,排除干扰, 有自己的判断,当然基础是自己技术扎实。
有条件的团队尽快升级jdk11,时间拖得越久,升级的成本越大。