Skip to content

Instantly share code, notes, and snippets.

@ayago
Last active August 1, 2019 08:30
Show Gist options
  • Save ayago/7a8ce4f002e407f1644da721aad951d1 to your computer and use it in GitHub Desktop.
Save ayago/7a8ce4f002e407f1644da721aad951d1 to your computer and use it in GitHub Desktop.
Bind/Flat map nested stream
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.String.format;
import static java.util.Arrays.asList;
@Slf4j
public class BindNestedStreamSample {
public static void main(String[] args) {
List<ClassA> aLists = asList(
new ClassA("1",
asList(
new ClassB("a", asList(
new ClassC("I"))))),
new ClassA("2",
asList(
new ClassB("a", asList(
new ClassC("I"),
new ClassC("II")
))))
);
System.out.println("Imperative collect: "+imperativeCollect(aLists));
System.out.println("Declarative collect: "+declarativeCollect(aLists));
}
private static List<String> imperativeCollect(List<ClassA> aList){
List<String> strings = new ArrayList<>();
for (ClassA a: aList){
for(ClassB b: a.bList){
for(ClassC c: b.cList) {
String string = stringify(a).apply(b).apply(c);
strings.add(string);
}
}
}
return strings;
}
private static List<String> declarativeCollect(List<ClassA> aList){
return bindNestedStream(BindNestedStreamSample::stringify)
.apply(aList.stream())
.apply(a -> a.bList.stream())
.apply(b -> b.cList.stream())
.collect(Collectors.toList());
}
private static Function<ClassB, Function<ClassC, String>> stringify(ClassA a){
return b -> c -> format("%s-%s-%s", a.name, b.name, c.name);
}
//flattening nested streams with reference to parent. A comprehension pattern
//equivalent to
//
//Stream aStream;
//Stream bStream = a -> stream(a)
//Stream cStream = b -> stream(b)
//
//for(A a: aStream){
// for(B b: bStream(a)){
// for(C c: cStream(b)){
// f(a, b, c)
// }
// }
//}
private static <A, B, C, D> Function<Stream<A>,
Function<Function<A, Stream<B>>,
Function<Function<B, Stream<C>>, Stream<D>>>> bindNestedStream(
Function<A, Function<B, Function<C, D>>> f) {
return a -> b -> c ->
a.flatMap(x ->
b.apply(x).flatMap(y ->
c.apply(y).map(z ->
f.apply(x).apply(y).apply(z)
)
)
);
}
private static class ClassA {
private final String name;
final List<ClassB> bList;
private ClassA(String name, List<ClassB> bList) {
this.name = name;
this.bList = bList;
}
}
private static class ClassB {
private final String name;
final List<ClassC> cList;
private ClassB(String name, List<ClassC> cList) {
this.name = name;
this.cList = cList;
}
}
private static class ClassC {
private final String name;
ClassC(String name) {
this.name = name;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment