Java 8 toMap IllegalStateException 重复键
Posted
技术标签:
【中文标题】Java 8 toMap IllegalStateException 重复键【英文标题】:Java 8 toMap IllegalStateException Duplicate Key 【发布时间】:2015-04-30 16:10:01 【问题描述】:我有一个包含以下格式数据的文件
1
2
3
我想将其加载为(1->1), (2->1), (3->1)
这是 Java 8 代码,
Map<Integer, Integer> map1 = Files.lines(Paths.get(inputFile))
.map(line -> line.trim())
.map(Integer::valueOf)
.collect(Collectors.toMap(x -> x, x -> 1));
我收到以下错误
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 1
如何解决这个错误?
【问题讨论】:
当文件有两次相同的编号时,您希望发生什么? 如果有这样的情况,我想获取出现次数作为该键的值。因此,如果说密钥 2 在文件中出现 4 次,那么它将是 (2->4)。 那你就需要使用这个方法了:docs.oracle.com/javase/8/docs/api/java/util/stream/… 如果样本数据实际上包含重复项,我认为这个问题会更好 我遇到了同样的问题,错误信息不是误导吗?错误消息说重复键并打印出值 【参考方案1】:如果您想将值映射到 1,pramodh 的回答很好。但如果您不想总是映射到常量,使用“合并函数”可能会有所帮助:
Map<Integer, Integer> map1 = Files.lines(Paths.get(inputFile))
.map(line::trim())
.map(Integer::valueOf)
.collect(Collectors.toMap(x -> x, x -> 1, (x1, x2) -> x1));
上面的代码与问题中发布的几乎相同。但是如果它遇到duplicate key
,它不会抛出异常,而是通过应用合并函数来解决它,取第一个值。
【讨论】:
这更有用。谢谢@KeyMaker00【参考方案2】:如果文件中没有重复,代码将运行。
Map<Integer, Integer> map1 = Files.lines(Paths.get(inputFile))
.map(String::trim)
.map(Integer::valueOf)
.collect(Collectors.toMap(x -> x, x -> 1));
如果有重复项,请使用以下代码获取文件中该键的出现总数。
Map<Integer, Long> map1 = Files.lines(Paths.get(inputFile))
.map(String::trim)
.map(Integer::valueOf)
.collect(Collectors.groupingBy(x -> x, Collectors.counting());
【讨论】:
您可以使用collect(Collectors.groupingBy(x -> x, Collectors.counting()))
,这可能比toMap()
的3-arg 形式更清晰。此外,您还可以使用String::trim
代替line -> line.trim()
。
@StuartMarks,我收到 Collectors.groupingsBy(x -> x, Collectors.counting() 的循环推理错误
啊,counting()
累积成一个Long
,所以你必须将映射声明更改为Map<Integer,Long>
。
旁注:Files.lines
不会自动关闭文件 - 如果您经常这样做,您可能会遇到“打开的文件过多”错误。您可以使用 try-with-resources:try(Stream<String> lines = Files.lines(...)) lines.map(String::trim)....
@assylias 对于未来的读者,他们在11 中修复了这个问题:通过关闭流来关闭文件。以上是关于Java 8 toMap IllegalStateException 重复键的主要内容,如果未能解决你的问题,请参考以下文章
JDK1.8 Stream之toMap和groupingBy全参数的使用
JAVA集合05_Collection.toMap()应用三个重载方法解决重复key问题