重写了 Java8 新特性实战 部分内容,顺便同步到博客。
先看一下map和flatMap在Stream中的不同。
map 和 flatMap 都是将一个函数应用于集合中的每个元素,但不同的是map返回一个新的集合,flatMap是将每个元素都映射为一个集合,最后再将这个集合展平。
在实际应用场景中,如果map返回的是数组,那么最后得到的是一个二维数组,使用flatMap就是为了将这个二维数组展平变成一个一维数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class MapAndFlatMapExample { public static void main(String[] args) { List<String[]> listOfArrays = Arrays.asList( new String[]{"apple", "banana", "cherry"}, new String[]{"orange", "grape", "pear"}, new String[]{"kiwi", "melon", "pineapple"} );
List<String[]> mapResult = listOfArrays.stream() .map(array -> Arrays.stream(array).map(String::toUpperCase).toArray(String[]::new)) .collect(Collectors.toList());
System.out.println("Using map:"); System.out.println(mapResult);
List<String> flatMapResult = listOfArrays.stream() .flatMap(array -> Arrays.stream(array).map(String::toUpperCase)) .collect(Collectors.toList());
System.out.println("Using flatMap:"); System.out.println(flatMapResult); } }
|
运行结果:
1 2 3 4 5 6
| Using map:
Using flatMap:
|
最简单的理解就是flatMap可以将map的结果展开。
在Optional里面,当使用map()时,如果映射函数返回的是一个普通值,它会将这个值包装在一个新的Optional中。而使用flatMap时,如果映射函数返回的是一个Optional,它会将这个返回的Optional展平,不再包装成嵌套的Optional。
下面是一个对比的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public static void main(String[] args) { int userId = 1;
String cityUsingFlatMap = getUserById(userId) .flatMap(OptionalExample::getAddressByUser) .map(Address::getCity) .orElse("Unknown");
System.out.println("User's city using flatMap: " + cityUsingFlatMap);
Optional<Optional<Address>> optionalAddress = getUserById(userId) .map(OptionalExample::getAddressByUser);
String cityWithoutFlatMap; if (optionalAddress.isPresent()) { Optional<Address> addressOptional = optionalAddress.get(); if (addressOptional.isPresent()) { Address address = addressOptional.get(); cityWithoutFlatMap = address.getCity(); } else { cityWithoutFlatMap = "Unknown"; } } else { cityWithoutFlatMap = "Unknown"; }
System.out.println("User's city without flatMap: " + cityWithoutFlatMap); }
|
在Stream和Optional中正确使用flatMap可以减少很多不必要的代码。