Java 的 Stream 是 Java 8 引入的一个强大的 API,用于处理集合数据。Stream 提供了一种声明性的方法来处理数据,允许你以更简洁和可读的方式进行集合操作,如过滤、映射、排序和聚合等。
以下是一个简单的例子,展示了如何使用 Stream 来处理集合:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eve");
// 使用 Stream 过滤和转换集合
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A")) // 过滤以 "A" 开头的名字
.map(String::toUpperCase) // 转换为大写
.collect(Collectors.toList()); // 收集结果到一个 List
System.out.println(filteredNames); // 输出: [ALICE]
}
}
filter(Predicate<? super T> predicate)
用于筛选流中的元素,保留满足给定条件的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
map(Function<? super T, ? extends R> mapper)
将流中的每个元素转换为另一种形式。
List<String> names = Arrays.asList("Alice", "Bob");
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
将每个元素转换为一个流,然后将这些流合并成一个流。
List<List<String>> nestedList = Arrays.asList(Arrays.asList("a", "b"), Arrays.asList("c", "d"));
List<String> flatList = nestedList.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
distinct()
去除流中的重复元素。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
sorted()
对流中的元素进行自然排序。
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
sorted(Comparator<? super T> comparator)
使用自定义比较器对流中的元素进行排序。
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sortedNames = names.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
limit(long maxSize)
截取流中的前 maxSize 个元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
skip(long n)
跳过流中的前 n 个元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
collect(Collector<? super T, A, R> collector)
将流的元素收集到某种结果中,如 List、Set 等。
List<String> names = Arrays.asList("Alice", "Bob");
Set<String> nameSet = names.stream()
.collect(Collectors.toSet());
forEach(Consumer<? super T> action)
对流中的每个元素执行给定的操作。
List<String> names = Arrays.asList("Alice", "Bob");
names.stream().forEach(System.out::println);
reduce(BinaryOperator<T> accumulator)
使用累加器函数将流中的元素组合成一个结果。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
.reduce(0, Integer::sum);
findFirst()
返回流中的第一个元素的 Optional。
List<String> names = Arrays.asList("Alice", "Bob");
Optional<String> first = names.stream().findFirst();
findAny()
返回流中的任意一个元素的 Optional,适用于并行流。
List<String> names = Arrays.asList("Alice", "Bob");
Optional<String> any = names.stream().findAny();
count()
返回流中元素的数量。
List<String> names = Arrays.asList("Alice", "Bob");
long count = names.stream().count();
anyMatch(Predicate<? super T> predicate)
检查流中是否有任意一个元素匹配给定的谓词。
List<String> names = Arrays.asList("Alice", "Bob");
boolean hasAlice = names.stream().anyMatch(name -> name.equals("Alice"));
allMatch(Predicate<? super T> predicate)
检查流中的所有元素是否都匹配给定的谓词。
List<String> names = Arrays.asList("Alice", "Bob");
boolean allStartWithA = names.stream().allMatch(name -> name.startsWith("A"));
noneMatch(Predicate<? super T> predicate)
检查流中是否没有元素匹配给定的谓词。
List<String> names = Arrays.asList("Alice", "Bob");
boolean noneStartWithZ = names.stream().noneMatch(name -> name.startsWith("Z"));
peek(Consumer<? super T> action)
peek 是一个中间操作,允许你在流的每个元素上执行一个操作,通常用于调试或记录日志。它不会改变流的内容。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> result = names.stream()
.filter(name -> name.length() > 3)
.peek(name -> System.out.println("Filtered value: " + name))
.map(String::toUpperCase)
.collect(Collectors.toList());
generate(Supplier<T> s)
generate 是一个静态方法,用于创建一个无限流。你可以使用它来生成无限的随机数流或其他重复模式。
Stream<Double> randomNumbers = Stream.generate(Math::random).limit(5);
randomNumbers.forEach(System.out::println);
iterate(T seed, UnaryOperator<T> f)
iterate 也是一个静态方法,用于创建一个无限流,从一个初始值开始,并通过一个函数生成后续元素。
Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2).limit(5);
evenNumbers.forEach(System.out::println); // 输出: 0, 2, 4, 6, 8
takeWhile(Predicate<? super T> predicate)
takeWhile 是 Java 9 引入的一个方法,用于从流中获取满足条件的元素,直到遇到第一个不满足条件的元素为止。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> taken = numbers.stream()
.takeWhile(n -> n < 4)
.collect(Collectors.toList()); // 输出: [1, 2, 3]
dropWhile(Predicate<? super T> predicate)
dropWhile 也是 Java 9 引入的,用于丢弃流中满足条件的元素,直到遇到第一个不满足条件的元素为止。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> dropped = numbers.stream()
.dropWhile(n -> n < 4)
.collect(Collectors.toList()); // 输出: [4, 5, 6]
flatMapToInt, flatMapToDouble, flatMapToLong
这些方法用于将流中的元素映射为基本类型的流(如 IntStream、DoubleStream、LongStream),这在需要进行数值计算时非常有用。
List<String> numbers = Arrays.asList("1", "2", "3");
int sum = numbers.stream()
.flatMapToInt(num -> IntStream.of(Integer.parseInt(num)))
.sum(); // 输出: 6
collectingAndThen
collectingAndThen 是一个收集器的包装器,允许在收集操作完成后执行额外的转换。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String result = names.stream()
.collect(Collectors.collectingAndThen(
Collectors.joining(", "),
str -> "Names: " + str
));
System.out.println(result); // 输出: Names: Alice, Bob, Charlie