Java Stream中的flatMap()

时间:2020-01-09 10:35:16  来源:igfitidea点击:

在Java Stream中使用映射操作时,通过将给定函数应用于此流的所有元素来获得结果流。 Java Stream API还提供了flatMap()方法,该方法除了将给定功能应用于此流的所有元素之外,还对结果元素进行了展平,以使所有嵌套元素处于同一级别。

flatMap是一个中间操作。

flatMap方法签名

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

此处,映射器是应用于流中每个元素的无干扰,无状态函数。

R是新流的元素类型。

flatMap Java示例

让我们尝试通过几个示例来理解flatMap()如何使结构扁平化以及如何提供帮助。

假设有一个依次包含ArrayList的ArrayList,并且我们要计算列表中元素的总数。如果使用map函数,则元素数为2,因为map函数会将每个嵌套列表作为流元素。

public class FlatMapExample {
  public static void main(String[] args) {
    List<List<String>> list = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
    long noOfElements = list.stream().map(a -> a.stream()).count();
    System.out.println("Number of elements- "+ noOfElements);
  }
}

输出:

Number of elements- 2

当我们使用flatMap函数时,结构将被展平,以便正确计算元素的数量。

public class FlatMapExample {

	public static void main(String[] args) {
		List<List<String>> list = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
		long noOfElements = list.stream().flatMap(a -> a.stream()).count();
		System.out.println("Number of elements- "+ noOfElements);
	}
}

输出:

Number of elements- 4

如果要使用map函数以大写形式显示嵌套ArrayList中的元素,则返回List <Stream <String >>

public class FlatMapExample {
  public static void main(String[] args) {
    List<List<String>> list = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
    List<Stream<String>> resultlist = list.stream()
                              .map(a -> a.stream()
                              .map(String::toUpperCase))
                              .collect(Collectors.toList());
    resultlist.forEach(a -> a.forEach(System.out::println));
  }
}

如果在这种情况下使用flatMap,则两个列表都将被展平,因此返回值为List

public class FlatMapExample {
  public static void main(String[] args) {
    List<List<String>> list = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
    List<String> resultlist = list.stream()
                        .flatMap(a -> a.stream()
                        .map(String::toUpperCase))
                        .collect(Collectors.toList());
    resultlist.forEach(System.out::println);
  }
}

输出:

A
B
C
D

这是另一个具有列表列表的示例。有一个Order类,其中的字段项类型为List。现在,我们要显示所有订单中的所有项目。

public class Order {
  private String orderId;
  private List<String> items;
  public String getOrderId() {
    return orderId;
  }
  public void setOrderId(String orderId) {
    this.orderId = orderId;
  }
  public List<String> getItems() {
    return items;
  }
  public void setItems(List<String> items) {
    this.items = items;
  }
}
public class FlatMapExample {
  public static void main(String[] args) {
    // Create list of orders
    List<Order> listOfOrders = new ArrayList<Order>();
    Order order = new Order();
    order.setOrderId("1");
    order.setItems(Arrays.asList("Book", "Shoes", "Watch"));
    listOfOrders.add(order);
    order = new Order();
    order.setOrderId("2");
    order.setItems(Arrays.asList("Mobile", "Book"));
    listOfOrders.add(order);

    List<String> listOfItems = listOfOrders.stream()
                          .flatMap(o -> o.getItems()
                          .stream())
                          .collect(Collectors.toList());
    listOfItems.forEach(System.out::println);
  }
}

输出:

Book
Shoes
Watch
Mobile
Book

原始类型流的flatMap

还有一些flatMap()变体可用于获取Java中的原始类型流。

  • flatMapToInt(Function <?super T,?extended IntStream> mapper)–返回一个IntStream,该结果包含将该流的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。
  • flatMapToLong(Function <?super T,?extended LongStream> mapper)–返回一个LongStream,该结果包括将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。
  • flatMapToDouble(Function <?super T,?extended DoubleStream> mapper)–返回一个DoubleStream,该结果由将该流的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容组成的结果。

flatMapToInt Java示例

通过展平二维数组来获取IntStream。

int[][] numbers = {{7,8}, {4,5}, {3,4}};
IntStream iStream = Stream.of(numbers).flatMapToInt(n -> Arrays.stream(n));
iStream.forEach(System.out::println);

输出:

7
8
4
5
3
4