Java Stream的使用

158 阅读4分钟

Java Stream简介

Java Stream是Java 8引入的一种新特性,它允许开发者以声明式方式处理数据集合。Stream API提供了一种高效且易于理解的方法来处理集合中的数据,使得代码更加简洁和可读。Stream可以用于对集合进行过滤、映射、排序等操作,而无需编写复杂的循环结构。

一、创建Stream

在Java中,有多种方法可以创建Stream。以下是一些常见的方法:

从集合创建Stream:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
Stream<String> nameStream = names.stream();
从数组创建Stream:
String[] namesArray = {"Alice", "Bob", "Charlie", "David", "Eve"};
Stream<String> nameStream = Arrays.stream(namesArray);
使用Stream.of()方法创建Stream:
Stream<String> nameStream = Stream.of("Alice", "Bob", "Charlie", "David", "Eve");
创建无限Stream:
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);

二、Stream操作

Stream API提供了许多操作,可以对数据进行各种处理。以下是一些常见的Stream操作:

过滤(Filtering):
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
List<String> filteredNames = names.stream()
                                   .filter(name -> name.startsWith("A"))
                                   .collect(Collectors.toList());

在这个例子中,我们使用filter方法过滤出以"A"开头的名字,并将结果收集到一个新的列表中。

映射(Mapping):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream()
                                      .map(number -> number * number)
                                      .collect(Collectors.toList());

在这个例子中,我们使用map方法将每个数字映射到其平方,并将结果收集到一个新的列表中。

排序(Sorting):
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
List<String> sortedNames = names.stream()
                                 .sorted()
                                 .collect(Collectors.toList());

在这个例子中,我们使用sorted方法对名字列表进行排序,并将结果收集到一个新的列表中。

归约(Reducing):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);

在这个例子中,我们使用reduce方法计算数字列表的总和。

收集(Collecting):
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
Set<String> nameSet = names.stream()
                            .collect(Collectors.toSet());

在这个例子中,我们使用collect方法将名字列表收集到一个集合中。

统计(Statistics):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntSummaryStatistics stats = numbers.stream()
                                    .mapToInt(Integer::intValue)
                                    .summaryStatistics();

在这个例子中,我们使用summaryStatistics方法计算数字列表的统计信息,如最大值、最小值、平均值等。

并行处理(Parallel Processing):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
                 .reduce(0, (a, b) -> a + b);

在这个例子中,我们使用parallelStream方法并行处理数字列表,以提高性能。

三、中间操作(Intermediate Operations)

中间操作是对Stream进行转换的操作,它们返回一个新的Stream。以下是一些常见的中间操作:

distinct:

去除重复元素

List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 1, 4, 5, 4);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
peek:

在不改变Stream的情况下,对每个元素执行某个操作(通常用于调试)

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
List<String> uppercasedNames = names.stream()
                                    .peek(System.out::println)
                                    .map(String::toUpperCase)
                                    .collect(Collectors.toList());
skip和limit:

跳过一定数量的元素或限制Stream的大小

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> limitedNumbers = numbers.stream()
                                      .skip(2)
                                      .limit(5)
                                      .collect(Collectors.toList());

四、终止操作(Terminal Operations)

终止操作是对Stream进行最终处理的操作,它们返回一个非Stream的结果。以下是一些常见的终止操作:

forEach:

对每个元素执行某个操作。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
names.stream().forEach(System.out::println);
toArray:

将Stream转换为数组。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
String[] namesArray = names.stream().toArray(String[]::new);
anyMatch、allMatch和noneMatch:

检查Stream中的元素是否满足某个条件。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
boolean anyMatch = names.stream().anyMatch(name -> name.startsWith("A"));
boolean allMatch = names.stream().allMatch(name -> name.length() > 3);
boolean noneMatch = names.stream().noneMatch(name -> name.endsWith("Z"));
findFirst和findAny:

查找Stream中的第一个或任意一个元素。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
Optional<String> first = names.stream().findFirst();
Optional<String> any = names.stream().findAny();

收集器(Collectors)

Java Stream API提供了一个名为Collectors的工具类,它包含了许多用于收集Stream结果的方法。以下是一些常见的收集器:

joining:

将Stream中的字符串连接起来。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
String joinedNames = names.stream().collect(Collectors.joining(", "));
groupingBy:

根据某个属性对Stream中的元素进行分组。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
Map<Integer, List<String>> groupedNames = names.stream()
                                               .collect(Collectors.groupingBy(String::length));
partitioningBy:

根据某个条件将Stream中的元素分成两组。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Map<Boolean, List<Integer>> partitionedNumbers = numbers.stream()
                                                        .collect(Collectors.partitioningBy(n -> n % 2 == 0));
counting:

计算Stream中的元素数量。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
long count = names.stream().collect(Collectors.counting());
summarizingInt、summarizingLong和summarizingDouble:

计算Stream中的元素的统计信息。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));