2016-04-22 12 views
2

私は三つのクラスを持っていますとその量。グループと合計深くネストされたリストは、

私が持っている場合は、次のとおりです、私はgroupingByと組み合わせの数を試した

"foo", "unit", 2 
"foo", "another_unit", 1 

toMap

Unit unit1 = new Unit("unit"); 
Unit unit2 = new Unit("unit"); 
Unit unit3 = new Unit("another_unit"); 

Compartment compartment = new Compartment("foo", newArrayList(unit1, unit2, unit3)); 

Supply supply = new Supply(newArrayList(compartment)); 

のJavaストリーム使用して、私のような何かを取得したいと思いそのような幸運はありません。

私の最新の試みのようなものです:

私は非常に近いですが、私は私がキー以来 Mapを使用することができませんでしたね、 itemIdが異なる containerNumber

であり、複数回可能性を感じ
Map<String, List<Map<String, List<Unit>>>> result = supply.getCompartments() 
    .stream() 
    .collect(groupingBy(Compartment::getItemId, 
      mapping(compartment -> compartment.getUnits().stream().collect(groupingBy(Unit::getContainerNumber)), toList()))); 

答えて

1

あなたは正しいアイデアがあります。欠落しているのは、マッピングコレクタではなく、フラットなマッピングコレクタがダウンストリームコレクタとして必要なことです。

悲しいことに、このコレクタはJava 8には組み込まれていませんが、Java 9(JDK-8071600)にはCollectors.flatMapping(mapper, downstream)が存在します。 Javaの8のために、一つはこのようにそれを再実装することができます

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(), 
      (acc, t) -> { 
       try (Stream<? extends U> stream = mapper.apply(t)) { 
        if (stream != null) { 
         stream.sequential().forEach(u -> downstreamAccumulator.accept(acc, u)); 
        } 
       } 
      }, 
      downstream.combiner(), 
      downstream.finisher(), 
      downstream.characteristics().toArray(new Characteristics[downstream.characteristics().size()]) 
      ); 
} 

その後、あなたの希望のマップを構築するために、このコレクタを使用することができます。

Map<String, Map<String, List<Unit>>> map = 
    supply.getCompartments() 
      .stream() 
      .collect(groupingBy(
      Compartment::getItemId, 
      flatMapping(c -> c.getUnits().stream(), groupingBy(Unit::getContainerNumber)) 
     )); 
関連する問題