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));