介绍
我们知道,Java 8中的Stream是一个非常强大的工具,可以帮助我们轻松地对集合进行操作。而flatMap方法就是Stream中的一个非常实用的方法,它可以将一个嵌套的集合“扁平化”,使得我们可以更方便地对集合进行操作。
举个例子,假设我们有一个List,里面包含了多个字符串数组。如果我们想要将这些字符串数组合并成一个单独的列表,我们可以使用flatMap方法。具体的做法是,先将每个字符串数组转换成一个Stream,然后使用flatMap方法将所有Stream合并成一个Stream。最终,我们就可以得到一个包含所有字符串的单独的列表。
另一个例子是,假设我们有一个List,里面包含了多个整数数组。如果我们想要将这些整数数组中的所有元素相加,我们可以使用flatMap方法。具体的做法是,先将每个整数数组转换成一个IntStream,然后使用flatMap方法将所有IntStream合并成一个IntStream。最终,我们就可以使用sum方法得到所有元素的总和。
总的来说,flatMap方法就是将一个嵌套的集合“扁平化”,使得我们可以更方便地对集合进行操作。它的使用非常灵活,可以用于许多场景,包括数据处理、集合操作、关联查询等等。
使用场景
- 从多个集合中获取所有元素
假设我们有两个列表,分别存储了用户的用户名和邮箱地址。现在,我们想要将这两个列表合并成一个列表,包含所有的用户名和邮箱地址。可以使用flatMap方法将这两个列表合并成一个Stream,然后使用collect方法将所有元素收集到一个列表中。
List<String> usernames = Arrays.asList("alice", "bob", "charlie");
List<String> emails = Arrays.asList("alice@example.com", "bob@example.com", "charlie@example.com");
List<String> all = Stream.of(usernames, emails)
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(all);
// Output: [alice, bob, charlie, alice@example.com, bob@example.com, charlie@example.com]
- 处理嵌套的集合
假设我们有一个嵌套的集合,包含了多个列表。我们想要将这些列表中的所有元素合并成一个单独的列表。可以使用flatMap方法将每个列表转换成一个Stream,然后使用flatMap方法将所有Stream合并成一个Stream。最终,我们就可以得到一个包含所有元素的单独的列表。
perlCopy codeList<String> usernames = Arrays.asList("alice", "bob", "charlie");
List<String> emails = Arrays.asList("alice@example.com", "bob@example.com", "charlie@example.com");
List<String> all = Stream.of(usernames, emails)
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(all);
// Output: [alice, bob, charlie, alice@example.com, bob@example.com, charlie@example.com]
- 进行关联查询
假设我们有两个表,一个是用户表,一个是订单表。每个用户可能有多个订单,我们想要查询每个用户的所有订单。可以使用flatMap方法将每个用户映射为它的所有订单,然后将所有订单放在一个Stream中,从而进行关联查询。
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public class Order {
private int userId;
private int orderId;
private int price;
public Order(int userId, int orderId, int price) {
this.userId = userId;
this.orderId = orderId;
this.price = price;
}
public int getUserId() {
return userId;
}
public int getOrderId() {
return orderId;
}
public int getPrice() {
return price;
}
}
List<User> users = Arrays.asList(
new User(1, "Alice"),
new User(2, "Bob"),
new User(3, "Charlie")
);
List<Order> orders = Arrays.asList(
new Order(1, 1001, 10),
new Order(1, 1002, 20),
new Order(2, 1003, 30),
);
List<Order> allOrders = users.stream()
.flatMap(user -> orders.stream()
.filter(order -> order.getUserId() == user.getId()))
.collect(Collectors.toList());
System.out.println(allOrders);
// Output: [Order(userId=1, orderId=1001, price=10), Order(userId=1, orderId=1002, price=20), Order(userId=2, orderId=1003, price=30)]
在这个例子中,我们首先使用flatMap方法将每个用户映射为它的所有订单。对于每个用户,我们使用过滤器将所有订单中属于该用户的订单筛选出来,并放在一个新的Stream中。最终,我们得到了一个包含所有订单的列表。
- 处理多维数组
如果我们有一个多维数组,可以使用flatMap方法将其转换为一个一维数组。
int[][] matrix = {{1, 2}, {3, 4}, {5, 6}};
int[] flattened = Arrays.stream(matrix)
.flatMapToInt(Arrays::stream)
.toArray();
System.out.println(Arrays.toString(flattened));
// Output: [1, 2, 3, 4, 5, 6]
在这个例子中,我们首先使用Arrays.stream方法将多维数组转换为一个Stream。然后,我们使用flatMapToInt方法将每个子数组映射为一个IntStream,将所有IntStream合并成一个IntStream。最终,我们使用toArray方法将所有元素收集到一个一维数组中。
- 拉平Map
在Java 9及以上版本中,flatMap还可以用于将Map中的键值对转换为一个Stream。假设我们有一个Map,其中每个键都对应一个列表。我们想要将所有的列表中的元素合并成一个单独的列表。可以使用flatMap方法将每个键值对转换为一个Stream,然后使用flatMap方法将所有Stream合并成一个Stream。
Map<String, List<Integer>> map = new HashMap<>();
map.put("A", Arrays.asList(1, 2, 3));
map.put("B", Arrays.asList(4, 5, 6));
map.put("C", Arrays.asList(7, 8, 9));
List<Integer> allValues = map.entrySet().stream()
.flatMap(entry -> entry.getValue().stream())
.collect(Collectors.toList());
System.out.println(allValues);
// Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
在这个例子中,我们首先使用entrySet方法将Map转换为一个Set。然后,我们使用flatMap方法将每个键值对映射为它的所有值,将所有值放在一个新的Stream中。最终,我们得到了一个包含所有值的列表。