一、map()与 flatMap() 功能说明,两者的相同点与不同点
1、功能说明
(1)map(),对集合中的元素逐个进行函数操作映射成另外一个。
(2)flatMap,接收一个函数作为参数,将流中的每个值都转换为另一个流,然后把所有的流都连接成一个流。
【示例一】
// 如果我们把List中的 所有字符变为大写。
Map 操作
[['a', 'b', 'c'], ['d', 'e', 'f']] =>> [['A', 'B', 'C'], ['D', 'E', 'F']]
FlatMap 操作
[['a', 'b', 'c'], ['d', 'e', 'f']] =>> ['A', 'B', 'C', 'D', 'E', 'F']
2、相同点
Map 和 FlatMap,都是流中 集合数据类型的 转换操作符。
3、不同点
(1)Map 是 将 集合数据中每一个元素作为 参数 传入的lambda表达后进行转换操作, 得到的结果用一个ArrayList 收集起来。
(2)FlatMap, Flat(扁平化),顾名思义, 就是在Map的基础上,会将集合的数据结构给展开。flatMap()方法用于将流中的每个元素转换为一个新的流,然后将这些新的流合并成一个流。
(3)FlatMap传入的lambda表达式的返回值,必须为集合接口类型。如:flatMap(Arrays::stream)、flatMap(List::stream)
二、源码分析【待深入学习】
1、map() 源码分析
map是集合接口Iterable的一个扩展函数,它有两个泛型 T和R, T是集合接口容器包裹的元素数据类型,以上面的【示例一】例子就是List, R 是lambda表达式的返回类型,也是map操作后所得到的集合容器装载元素的数据类型,以上面的【示例一】例子就是<List>。
transform是一个lambda表达式,或说函数类型,它的参数类型是T,返回值类型是R,当我们调用了map操作符后,它干了什么呢?它就是直接 将一个 新的ArrayList 和 lambda表达式一并传入mapTo()方法中。
那么它在mapTo方法中做了什么呢?非常简单,就是遍历一遍 集合, 以上面的例子 遍历的结果就是 [‘a’, ‘b’, ‘c’] 和 [‘d’, ‘e’, ‘f’]两个元素,将这些元素分别执行lambda表达式,将得到的结果用那个 新的ArrayList收集起来。
2、flatMap() 源码分析
flatMap也是一样的,是集合接口Iterable的一个扩展函数,操作符需要传入一个lambda表达式,不同的是这个lambda表达式的返回值是一个 集合接口类型(list, set等)。它创建了一个新的ArrayList实例,把实例和lambda表达式一并作为参数传入 flatMapTo方法中。
我们看看flatMapTo干了啥?flatMap先是遍历一遍集合内的元素,将每一个元素按照lambda表达式的逻辑进行处理, 处理后的结果(集合接口类型)将它添加到 新的ArrayList, 注意了,它添加的方式是 addAll(集合接口)。这个方法就自然而然把元素的集合结构给展开了。
三、代码实践
1、代码
package jdk8;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Description JDK8特性:Stream流操作中的map()与 flatMap()
**/
public class StreamTest {
/* 做测试用的数据 */
private List<Employee> getChineseList(){
List<Employee> employeeList = Arrays.asList(
new Employee( "张三", 23),
new Employee("李四", 25),
new Employee( "王五", 26),
new Employee( "赵子龙", 20)
);
return employeeList;
}
private List<Employee> getBritishList(){
List<Employee> employeeList = Arrays.asList(
new Employee( "tom", 23),
new Employee("lisa", 25),
new Employee( "alis", 26)
);
return employeeList;
}
private List<List<Employee>> getAllPeople(){
List<List<Employee>> allPeople = new ArrayList<>();
allPeople.add(getChineseList());
allPeople.add(getBritishList());
return allPeople;
}
/**
* 验证 map() 方法的基础功能
*/
private void testMap(){
System.out.println("验证 map() 方法的基础功能");
List<Employee> employeeList = getChineseList();
List<String> nameList = employeeList.stream()
.map(employee -> employee.getName())
.collect(Collectors.toList());
System.out.println(" nameList = " + nameList);
}
/**
* 将三维数据,经过两次 flatMap() 方法处理后,变为一维数组
*/
private void testFlatMap(){
System.out.println("将三维数据,经过两次 flatMap() 方法处理后,变为一维数组");
//三维数组
String [][][] strArrays = {
{
{"a","b"},{"c","d","e"},{"f"}
},
{
{"g"},{"h"}
},
{
{"i"}
}
};
List<String> strList = Arrays.stream(strArrays)
.flatMap(Arrays::stream)
.flatMap(Arrays::stream)
.collect(Collectors.toList());
System.out.println(" strList = " + strList);
}
private void testMapOfList(){
System.out.println("testMapOfList(),经过map()处理后,得到的是一个多维数组");
List<Employee> employeeList = getChineseList();
List<List<String>> collect = employeeList.stream()
.map(employee -> {
List<String> list = new ArrayList<>();
list.add(employee.getName());
return list;
})
.collect(Collectors.toList());
System.out.println(" map() 处理后的 collect = " + collect);
}
private void testFlatMapOfList(){
System.out.println("testFlatMapOfList(),经过flatMap()处理后,得到的是一个一维数组");
List<Employee> employeeList = getChineseList();
List<String> collect2 = employeeList.stream()
.map(employee -> {
List<String> list = new ArrayList<>();
list.add(employee.getName());
return list;
})
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(" flatMap() 处理后的 collect2 = " + collect2);
}
public static void main(String[] args) {
StreamTest obj = new StreamTest();
obj.testMap();
obj.testFlatMap();
obj.testMapOfList();
obj.testFlatMapOfList();
}
}
@Getter
@Setter
@AllArgsConstructor
class Employee{
private String name;
private int age;
}
2、控制台打印日志
验证 map() 方法的基础功能
nameList = [张三, 李四, 王五, 赵子龙]
将三维数据,经过两次 flatMap() 方法处理后,变为一维数组
strList = [a, b, c, d, e, f, g, h, i]
testMapOfList(),经过map()处理后,得到的是一个多维数组
map() 处理后的 collect = [[张三], [李四], [王五], [赵子龙]]
testFlatMapOfList(),经过flatMap()处理后,得到的是一个一维数组
flatMap() 处理后的 collect2 = [张三, 李四, 王五, 赵子龙]