List> userLists
, 这属于套娃现象,而最终我们只想得到List userList 对象,即将多维集合,变成一个集合,相当于压缩,俗称扁平化。之前在做开发的时候,遇到如下需求:
给List对象,需要获取到List对象
// 解释:一个房间有自己的房间号,里面有一堆人,每个人都有面子
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Room {
private int number;
private List<People> peopleList;
@Data
@NoArgsConstructor
@AllArgsConstructor
static class People {
private String name;
}
}
如下:如果只是使用普通的map方法且里面是直接getPeopleList()方法,则得到的是 List 对象。> collect
public class demo {
public static void main(String[] args) {
final List<Room> roomList = initRoom();
List<List<Room.People>> collect = roomList.stream()
.map(Room::getPeopleList)
.collect(Collectors.toList());
}
}
通常遇到这情况,一般人解决就是在遍历一次,如下:
public class demo {
public static void main(String[] args) {
final List<Room> roomList = initRoom();
List<List<Room.People>> collect = roomList.stream()
.map(Room::getPeopleList)
.collect(Collectors.toList());
// 1.先new ArrayList<>() 准备存储String字符串
List<String> peopleNameList = new ArrayList<>();
// 2. 这里就得套两层的foreach了
// 因为初始化是List>对象
// 第一次foreach中peopleList 是List对象
collect.forEach(peopleList -> {
// 第二次foreach中people 是People对象
peopleList.forEach(people -> {
peopleNameList.add(people.getName());
});
});
}
而有的人可能会在上面的基础上,再进一步优化为如下:
public class demo {
public static void main(String[] args) {
final List<Room> roomList = initRoom();
List<String> peopleNameList = new ArrayList<>();
// 直接一直使用stream流的foreach
// 虽然是比上面代码优雅多了,但两个foreach,怎么看都不舒服
roomList.stream().forEach(room -> {
room.getPeopleList().forEach(people -> {
peopleNameList.add(people.getName());
});
});
}
}
flatMap就是用于多层结构的扁平化,如下:
public class demo {
public static void main(String[] args) {
final List<Room> roomList = initRoom();
List<String> peopleNameList = roomList.stream()
.map(Room::getPeopleList)
.flatMap(Collection::stream)
.map(Room.People::getName)
.collect(Collectors.toList());
}
}

代码如下:
public class demo {
public static void main(String[] args) {
final List<Room> roomList = initRoom();
// Map方法
List<String> peopleNameList = new ArrayList<>();
roomList.stream().forEach(room -> {
room.getPeopleList().forEach(people -> {
peopleNameList.add(people.getName());
});
});
// flatMap 方法
List<String> peopleNameList2 = roomList.stream()
.map(Room::getPeopleList)
.flatMap(Collection::stream)
.map(Room.People::getName)
.collect(Collectors.toList());
}
// 初始化10条数据
private static List<Room> initRoom() {
return IntStream.range(1, 11)
.mapToObj(num -> new Room(num, Arrays.asList(new Room.People("name:" + num), new Room.People("name:" + 10 * num))))
.collect(Collectors.toList());
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Room {
private int number;
private List<People> peopleList;
@Data
@NoArgsConstructor
@AllArgsConstructor
static class People {
private String name;
}
}
}