【问题标题】:Java-Stream, toMap with duplicate keysJava-Stream,具有重复键的 toMap
【发布时间】:2018-02-06 18:21:07
【问题描述】:

所以可能有一个 abc 用于多次付款,现在我有:

//find abc id for each payment id
Map<Long, Integer> abcIdToPmtId = paymentController.findPaymentsByIds(pmtIds)
          .stream()
          .collect(Collectors.toMap(Payment::getAbcId, Payment::getPaymentId));

但后来我意识到这可能有重复的键,所以我希望它返回一个

Map<Long, List<Integer>> abcIdToPmtIds 

其中一个条目将包含一个 abc 和他的几笔付款。

我知道我可能可以使用groupingBy,但我想我只能使用Map&lt;Long, List&lt;Payments&gt;&gt;

【问题讨论】:

    标签: java java-stream


    【解决方案1】:

    使用其他 groupingBy 重载。

    paymentController.findPaymentsByIds(pmtIds)
          .stream()
          .collect(
              groupingBy(Payment::getAbcId, mapping(Payment::getPaymentId, toList());
    

    【讨论】:

    • 很好的答案!对于那些我们需要稍微修改的版本以包含在地图中的全部付款而不是仅包含 ID:.collect(groupingBy(Payment::getId, mapping(payment -&gt; payment, toList())))
    【解决方案2】:

    问题陈述:正在转换SimpleImmutableEntry&lt;String, List&lt;String&gt;&gt; -> Map&lt;String, List&lt;String&gt;&gt;

    例如,您有一个 [A,[1]], [B,[2]], [A, [3]] 形式的 SimpleImmutableEntry 并且您希望您的地图看起来像这样:A -> [1 ,3] , B -> [2]。

    这可以通过 Collectors.toMap 完成,但 Collectors.toMap 仅适用于唯一键,除非您提供合并功能来解决冲突,如 java 文档中所述。

    https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-java.util.function.BinaryOperator-

    所以示例代码如下所示:

              .map(returnSimpleImmutableEntries)
              .collect(Collectors.toMap(SimpleImmutableEntry::getKey,
                                        SimpleImmutableEntry::getValue,
                                        (oldList, newList) -> { oldList.addAll(newList); return oldList; } ));
    

    returnSimpleImmutableEntries 方法返回 [A,[1]], [B,[2]], [A, [3]] 形式的条目,您可以在这些条目上使用您的收集器。

    【讨论】:

      【解决方案3】:

      Collectors.toMap:

      Map<Long, Integer> abcIdToPmtId = paymentController.findPaymentsByIds(pmtIds)
          .stream()
          .collect(Collectors.toMap(
              Payment::getAbcId, 
              p -> new ArrayList<>(Arrays.asList(p.getPaymentId())),
              (o, n) -> { o.addAll(n); return o; }));
      

      尽管将Collectors.groupingByCollectors.mapping 一起使用更清晰易读。

      你不需要流来做到这一点:

      Map<Long, Integer> abcIdToPmtId = new HashMap<>();
      paymentController.findPaymentsByIds(pmtIds).forEach(p ->
          abcIdToPmtId.computeIfAbsent(
                  p.getAbcId(),
                  k -> new ArrayList<>())
              .add(p.getPaymentId()));
      

      【讨论】:

        猜你喜欢
        • 2015-04-30
        • 2018-04-19
        • 2018-08-21
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 1970-01-01
        相关资源
        最近更新 更多