# Java 8中map()与flatMap()在Optional和Stream中的区别

在Java 8中,我们可以在OptionalStream经常看到map()flatMap()这两个方法,这两个方法是针对函数式特性引入的,两者功能上看似相近,但其实还是有很大区别的。让我们来了解一下吧。

# 1 Optional中的比较

我们会经常在Optional中使用到map()做对象转化,如下把一个整数转化成它的两倍:

Optional<Integer> num = Optional.of(33);
assertEquals(Optional.of(66),num.map(i -> i * 2));

然而,在一些更复杂的函数里,可能会返回一个Optional的结果,而不是我们直接需要可用的,就会造成了嵌套结构。看下面的代码来理解一下这种情况:

assertEquals(Optional.of(Optional.of(66)),
             Optional.of(33).map(i -> Optional.of(i * 2)));

结果使用map()就返回了一个Optional<Optional<Integer>>嵌套结构的结果。这时候,使用flatMap()能带来不一样的效果:

assertEquals(Optional.of(66),
             Optional.of(33).flatMap(i -> Optional.of(i * 2)));

# 2 Stream中的比较

这两个方法在Stream中的表现其实也是类似的。

map()会对序列包装一层Stream,而flatMap()则可以防止造成Stream<Stream<R>>式的嵌套。

//map
List<Integer> list = Stream.of(1, 2, 3)
  .map(i -> i * 2)
  .collect(Collectors.toList());
assertEquals(asList(2, 4, 6), list);

//flatMap
List<List<Integer>> myList = asList(asList(1, 2), singletonList(3));
List<Integer> result = myList.stream()
  .flatMap(Collection::stream)
  .collect(Collectors.toList());
assertEquals(asList(1, 2, 3), result);

例子中map()还是如一样做了转化处理工作;而flatMap()则在本来是List<List<Integer>>通过Stream的转化,变成了一个List<Integer>

需要注意的是,本来“1,2”是一组的,现在直接与“3”合成了一组。

# 3 总结

通过分析map()flatMap()OptionalStream中的区别,我觉得可以把flat理解为“展开、平铺”,把一个嵌套结构展开了。这两个方法非常常用,还是需要掌握的。

上次更新: 2023/8/18 23:39:36