介绍

我们知道,Java 8中的Stream是一个非常强大的工具,可以帮助我们轻松地对集合进行操作。而flatMap方法就是Stream中的一个非常实用的方法,它可以将一个嵌套的集合“扁平化”,使得我们可以更方便地对集合进行操作。

举个例子,假设我们有一个List,里面包含了多个字符串数组。如果我们想要将这些字符串数组合并成一个单独的列表,我们可以使用flatMap方法。具体的做法是,先将每个字符串数组转换成一个Stream,然后使用flatMap方法将所有Stream合并成一个Stream。最终,我们就可以得到一个包含所有字符串的单独的列表。

另一个例子是,假设我们有一个List,里面包含了多个整数数组。如果我们想要将这些整数数组中的所有元素相加,我们可以使用flatMap方法。具体的做法是,先将每个整数数组转换成一个IntStream,然后使用flatMap方法将所有IntStream合并成一个IntStream。最终,我们就可以使用sum方法得到所有元素的总和。

总的来说,flatMap方法就是将一个嵌套的集合“扁平化”,使得我们可以更方便地对集合进行操作。它的使用非常灵活,可以用于许多场景,包括数据处理、集合操作、关联查询等等。

使用场景

  1. 从多个集合中获取所有元素

假设我们有两个列表,分别存储了用户的用户名和邮箱地址。现在,我们想要将这两个列表合并成一个列表,包含所有的用户名和邮箱地址。可以使用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]
  1. 处理嵌套的集合

假设我们有一个嵌套的集合,包含了多个列表。我们想要将这些列表中的所有元素合并成一个单独的列表。可以使用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]
  1. 进行关联查询

假设我们有两个表,一个是用户表,一个是订单表。每个用户可能有多个订单,我们想要查询每个用户的所有订单。可以使用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中。最终,我们得到了一个包含所有订单的列表。

  1. 处理多维数组

如果我们有一个多维数组,可以使用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方法将所有元素收集到一个一维数组中。

  1. 拉平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中。最终,我们得到了一个包含所有值的列表。