이 (덕분에이 링크를 @shmosel하기 : 당신이 달성 할 수
private static Collector<Collection<SomeClassB>, ?, ImmutableList<SomeClassB>>
flatMapToImmutableList() {
return Collectors.collectingAndThen(Collectors.toList(),
listOfCollectionsOfB ->
listOfCollectionsOfB.stream()
.flatMap(Collection::stream)
.collect(GuavaCollectors.toImmutableList()));
}
당신이 계신), 자신 만의 수집기를 작성하여 원하는 것을 얻을 수 있습니다.
public static <T, D, R> Collector<T, ?, R> flatMapping(
Function<? super T, ? extends Stream<? extends D>> streamMapper,
Collector<? super D, ?, R> downstream) {
class Acc {
Stream.Builder<Stream<? extends D>> builder = Stream.builder();
void add(T t) {
builder.accept(streamMapper.apply(t));
}
Acc combine(Acc another) {
another.builder.build().forEach(builder);
return this;
}
R finish() {
return builder.build()
.flatMap(Function.identity()) // Here!
.collect(downstream);
}
}
return Collector.of(Acc::new, Acc::add, Acc::combine, Acc::finish);
}
이 도우미 메서드는 Collector.of
및 로컬 클래스 Acc
을 사용하여 제공된 streamMapper
함수에 의해 반환 된 스트림을 누적합니다.이 함수는 원본 스트림의 요소를 인수로 사용합니다. 이러한 스트림은 Stream.Builder
에 누적되어 수집기의 피니셔 기능이 적용될 때 작성됩니다.
이 스트림 스트림이 빌드 된 직후에는 스트림을 연결하기 만하기 때문에 ID 함수를 사용하여 플랫 맵핑됩니다. (스트림 스트림 대신 스트림 목록을 사용할 수는 있지만, Stream.Builder
은 매우 효율적이고 많이 사용되지 않는다고 생각합니다.)
Acc
도 주어진 Acc
의 스트림을이 Acc
의 스트림 빌더로 병합하는 결합 메소드를 구현합니다. 이 기능은 원본 스트림이 병렬 인 경우에만 사용됩니다.
다음은 귀하의 예제와 함께이 방법을 사용하는 방법은 다음과 같습니다
Map<String, Map<String, ImmutableList<SomeClassB>>> map = someListOfClassA.stream()
.filter(...)
.collect(
Collectors.groupingBy(SomeClassA::getSomeCriteriaA,
Collectors.groupingBy(SomeClassA::getSomeCriteriaB,
flatMapping(
a -> getSomeClassBsFromSomeClassA(a).stream(),
ImmutableList.toImmutableList()))));
편집이 : @Holger으로 아래 코멘트에 표시, 축적 스트림 빌더로 버퍼링 데이터에 대한 필요가 없습니다. 대신에 평면 매핑 수집기는 누적 기 함수에서 병합 실행을 수행하여 구현할 수 있습니다.Here is @Holger's own implementation of such collector, 나는 그의 동의를 그대로 여기에 복사하고있어 어떤 :
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> acc = downstream.accumulator();
return Collector.of(downstream.supplier(),
(a, t) -> {
try (Stream<? extends U> s = mapper.apply(t)) {
if (s != null) s.forEachOrdered(u -> acc.accept(a, u));
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics().toArray(new Collector.Characteristics[0]));
}
당신이해야합니다 자바 9 ['Collectors.flatMapping()'(http://download.java.net/java/jdk9/ 그룹의 다운 스트림 결과를 플랫화할 수있는 docs/api/java/util/stream/Collectors.html # flatMapping-java.util.function.Function-java.util.stream.Collector-). – shmosel