使用groupingBy的类的属性的Flat-Mapping Collector

时间:2017-01-26 16:47:44

标签: java java-8 java-stream

我有这门课。

class Assignment {
  private Integer index;
  private List<Quantity> quantities;
}

然后,我有一个该类的对象列表。

List<Assigment> assignments = new ArrayList<>();

有没有办法创建一个Map,其中包含AssignmentList<Quantity>的索引作为值?

这是我到目前为止所尝试过的。

assignments.stream().collect(groupingBy(Assignment::getIndex));

但是这给了我一个Map<Integer, List<Assignment>>,我想要一个Map<Integer, List<Quantity>>

我尝试过使用forEach方法 - 并且它有效 - 但我确信必须有一种方法可以在一个班轮中完成 - 或者至少只使用collect和{{ 1}}方法

1 个答案:

答案 0 :(得分:13)

看起来没有平面映射收集器可以用作Java8中groupingBy的下游,但Java9已经提出并接受它:https://bugs.openjdk.java.net/browse/JDK-8071600

public static <T, U, A, R>
    Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
                                   Collector<? super U, A, R> downstream) {
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
        return Collector.of(downstream.supplier(),
                            (r, t) -> mapper.apply(t).sequential().forEach(u -> downstreamAccumulator.accept(r, u)),
                            downstream.combiner(),
                            downstream.finisher(),
                            downstream.characteristics().stream().toArray(Collector.Characteristics[]::new));
    } 

如果您使用该方法,并向quantities添加Assignment方法并返回Stream<Quantity>,则可以使用此代码:

Map<Integer, List<Quantity>> result = assignments.stream()
    .collect(groupingBy(Assignment::getIndex, 
        flatMapping(Assignment::quantities, toList())));