一、前提建三个类
class Foo {
String name;
List<Bar> bars = new ArrayList<>();
Foo(String name) {
this.name = name;
}
}
class Bar {
String name;
Bar(String name) {
this.name = name;
}
}
class Outer {
Nested nested;
}
class Nested {
Inner inner;
}
class Inner {
String foo;
}
二、 写一个测试方法
@Test
public void testFlatMap(){
/**
* 我们创建了包含三个foo的集合,每个foo中又包含三个 bar。
* */
List<Foo> foos = new ArrayList<>();
// 创建 foos 集合
IntStream.range(1, 4).forEach(i ->
foos.add(new Foo("Foo" + i)));
// 创建 bars 集合
foos.forEach(f ->
IntStream
.range(1, 4)
.forEach(i -> f.bars.add(new Bar("Bar" + i + " <- " + f.name))));
/***
* flatMap 的入参接受一个返回对象流的函数。为了处理每个foo中的bar,我们需要传入相应 stream 流:
*/
foos.stream()
.flatMap(f -> f.bars.stream())
.forEach(b -> System.out.println(b.name));
/**
Bar1 <- Foo1
Bar2 <- Foo1
Bar3 <- Foo1
Bar1 <- Foo2
Bar2 <- Foo2
Bar3 <- Foo2
Bar1 <- Foo3
Bar2 <- Foo3
Bar3 <- Foo3
*/
/**
* 如上所示,我们已成功将三个 foo对象的流转换为九个bar对象的流。
* 最后,上面的这段代码可以简化为单一的流式操作:
*/
IntStream.range(1, 4)
.mapToObj(i -> new Foo("Foo" + i))
.peek(f -> IntStream.range(1, 4)
.mapToObj(i -> new Bar("Bar" + i + " <- " +f.name))
.forEach(f.bars::add))
.flatMap(f -> f.bars.stream())
.forEach(b -> System.out.println(b.name));
/**
* flatMap也可用于Java8引入的Optional类。
* Optional的flatMap操作返回一个Optional或其他类型的对象。
* 所以它可以用于避免繁琐的null检查。
* 接下来,让我们创建层次更深的对象:
*/
/**
* 为了处理从 Outer 对象中获取最底层的 foo 字符串,
* 你需要添加多个null检查来避免可能发生的NullPointerException,如下所示:
*/
Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
System.out.println(outer.nested.inner.foo);
}
/**
* 我们还可以使用Optional的flatMap操作,来完成上述相同功能的判断,且更加优雅:
*/
Optional.of(new Outer())
.flatMap(o -> Optional.ofNullable(o.nested))
.flatMap(n -> Optional.ofNullable(n.inner))
.flatMap(i -> Optional.ofNullable(i.foo))
.ifPresent(System.out::println);
}
}