【问题标题】:Spliterator causing duplicate key exception while for loop does not拆分器导致重复键异常,而 for 循环不会
【发布时间】:2017-05-27 02:16:41
【问题描述】:

我正在使用 Java 8 流。

当我使用拆分器添加到我的地图时,我得到重复键异常,但使用标准 for 循环不会引发异常。

// This works
Map<Integer, String> myMap = new HashMap<>();
for (Row row : result.result()) {
    myMap.put(row.get(0, Integer.class), null);
}

// This throws exception
myMap = StreamSupport.stream(result.result().spliterator(), true)
    .collect(Collectors.toMap(row -> row.get(0, Integer.class), row -> ""));

如果有什么不同,result 是 Cassandra 结果集,row 是 Cassandra 行。

【问题讨论】:

  • 示例问题数据?
  • 您最好创建一个minimal reproducible example,它可能会从问题中消除 cassandra,并且更通用,因此对问题的未来访问者更有用。

标签: java cassandra java-8 java-stream


【解决方案1】:

当您使用标准 for 循环时,如果您放置了一个已存在于 Map 中的键,则旧值将被新值替换。

另一方面,toMap 收集器的 2 个参数会在多个值映射到同一个键时引发异常。

为避免这种情况,您需要提供一个合并函数来处理此类冲突。

例如:

myMap = 
    StreamSupport.stream(result.result().spliterator(), true)
                 .collect(Collectors.toMap(row -> row.get(0, Integer.class), 
                                           row -> "",
                                           (v1,v2) -> v2));

这将采用其中一个值并在发生冲突时忽略另一个值。您可以选择其他合并功能,例如追加两个值:

(v1,v2) -> v1 + ", " + v2

正如 Eugene 评论的那样,结果按相遇顺序合并到 Map 中。

【讨论】:

  • also.. 看看那里有一个Row,我假设一些 SQL ......如果底层结果没有排序(通常不是)这个(以及 for 循环) 可能会从运行到运行返回不同的结果。但我猜 OP 知道这一点
  • 这是一个 Cassandra 结果集。键按添加到 Cassandra 表的日期排序。因此,作为地图键的值不是数字顺序 1、2、3、4 ......它们可以是 4、1、3、2 所以没关系
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-09
相关资源
最近更新 更多