Java-Stream,带有重复键的toMap

时间:2018-02-06 18:21:08

标签: java java-stream

所以可能有几个支付abc,现在我有:

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

但是后来我认为这个chould有重复的键,所以我希望它返回一个

Map<Long, List<Integer>> abcIdToPmtIds 

其中一个条目将包含一个abc及其多次付款。

我知道我可以使用groupingBy,但我认为我只能Map<Long, List<Payments>>

3 个答案:

答案 0 :(得分:6)

使用其他groupingBy重载。

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

答案 1 :(得分:2)

问题陈述:转换SimpleImmutableEntry<String, List<String>>-> Map<String, List<String>>

对于实例,您具有此格式为[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]]形式返回条目,您可以在其中使用收集器。

答案 2 :(得分:1)

使用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()));