Stream流小记

Stream流小记

本文给出 Java Stream 流的详细介绍,包含常用方法及其示例。


一、Stream 流基础

Stream 是 Java 8 引入的用于处理集合数据的函数式工具,支持惰性求值(中间操作不执行,终端操作触发计算)。
核心操作

  • 中间操作:返回新的 Stream(如 filtermapsorted)。
  • 终端操作:触发计算并返回结果(如 collectforEachreduce)。

创建 Stream 的方式

// 集合转 Stream
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Stream<Integer> stream1 = list.stream();

// 数组转 Stream
int[] arr = {1, 2, 3};
IntStream stream2 = Arrays.stream(arr);

// 直接创建
Stream<String> stream3 = Stream.of("a", "b", "c");

二、常用 Stream 方法

1. filter(Predicate<T>)

功能:过滤元素,保留满足条件的元素。
示例:过滤偶数。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> even = numbers.stream()
    .filter(n -> n % 2 == 0) // 过滤偶数
    .collect(Collectors.toList()); // 终端操作
System.out.println(even); // [2,4]

注意:filter() 方法会保留条件成立(返回 true)的元素,过滤掉条件不成立(返回 false)的元素。切记!!!

2. map(Function<T, R>)

功能:将元素转换为另一种类型或格式。
示例:将字符串转为大写。

List<String> names = Arrays.asList("apple", "banana", "orange");
List<String> upperCase = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());
System.out.println(upperCase); // [APPLE, BANANA, ORANGE]

3. flatMap(Function<T, Stream<R>>)

功能:将每个元素转换为 Stream,然后扁平化为一个 Stream。
示例:将二维数组转为一维数组。

List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4)
);
List<Integer> flatList = nestedList.stream()
    .flatMap(List::stream) // 将每个子列表转为 Stream,合并成一个 Stream
    .collect(Collectors.toList());
System.out.println(flatList); // [1,2,3,4]

4. sorted()

功能:对元素排序。
示例:升序排序字符串。

List<String> fruits = Arrays.asList("banana", "apple", "orange");
List<String> sorted = fruits.stream()
    .sorted() // 默认自然排序(按字母顺序)
    .collect(Collectors.toList());
System.out.println(sorted); // [apple, banana, orange]

5. distinct()

功能:去重(基于 equals() 方法)。
示例:去除重复数字。

List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> unique = duplicates.stream()
    .distinct()
    .collect(Collectors.toList());
System.out.println(unique); // [1,2,3]

6. peek(Consumer<T>)

功能:用于调试(类似 forEach,但返回 Stream)。
示例:查看过滤后的中间结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
List<Integer> result = numbers.stream()
    .filter(n -> n > 2)
    .peek(n -> System.out.println("Filtered: " + n)) // 输出过滤后的元素
    .collect(Collectors.toList());
// 输出:Filtered: 3, Filtered:4

7. limit(n)

功能:限制结果数量。
示例:取前两个元素。

List<String> colors = Arrays.asList("red", "green", "blue", "yellow");
List<String> limited = colors.stream()
    .limit(2)
    .collect(Collectors.toList());
System.out.println(limited); // [red, green]

8. skip(n)

功能:跳过前 n 个元素。
示例:跳过前两个元素。

List<String> colors = Arrays.asList("red", "green", "blue", "yellow");
List<String> skipped = colors.stream()
    .skip(2)
    .collect(Collectors.toList());
System.out.println(skipped); // [blue, yellow]

9. collect(Collector)

功能:将 Stream 结果收集到集合或对象中。
示例:收集到 List 和 Map。

List<String> fruits = Arrays.asList("apple", "banana", "apple");
Map<String, Long> count = fruits.stream()
    .collect(Collectors.groupingBy(
        Function.identity(), 
        Collectors.counting()
    ));
System.out.println(count); // {apple=2, banana=1}

10. reduce(BinaryOperator<T>)

功能:归约操作(如求和、乘积)。
示例:求和。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
    .reduce(0, Integer::sum); // 初始值为 0,使用 sum 累加
System.out.println(sum); // 10

11. count()

功能:统计元素数量。
示例:统计偶数个数。

long evenCount = Arrays.asList(1, 2, 3, 4, 5).stream()
    .filter(n -> n % 2 == 0)
    .count();
System.out.println(evenCount); // 2

12. max(Comparator)min(Comparator)

功能:获取最大/最小值。
示例:找最大值。

Optional<Integer> max = Arrays.asList(1, 5, 3).stream()
    .max(Integer::compareTo); // 或 .max(Comparator.naturalOrder())
System.out.println(max.orElse(0)); // 5

13. anyMatch(Predicate)allMatch(Predicate)noneMatch(Predicate)

功能:检查是否至少一个、全部或没有元素满足条件。
示例:检查是否包含偶数。

boolean hasEven = Arrays.asList(1, 3, 5).stream()
    .anyMatch(n -> n % 2 == 0);
System.out.println(hasEven); // false

14. findFirst()findAny()

功能:获取第一个或任意一个元素(并行流时 findAny 更高效)。
示例:获取第一个元素。

Optional<Integer> first = Arrays.asList(4, 2, 3).stream()
    .sorted()
    .findFirst();
System.out.println(first.orElse(0)); // 2

三、Stream 流的特性

  1. 惰性求值:中间操作不会立即执行,直到终端操作触发。
  2. 无状态:每个元素处理独立,不依赖其他元素。
  3. 消费性:元素只能遍历一次,之后需重新生成 Stream。

另外注意,多个方法可以叠加使用,如下:

import java.util.*;
import java.util.stream.*;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        
        // 过滤偶数、平方、求和
        int sum = numbers.stream()
            .filter(n -> n % 2 == 0)
            .map(n -> n * n)
            .reduce(0, Integer::sum);
        System.out.println(sum); // 20 + 36 = 56
    }
}

四、常见错误与注意事项

  1. Stream 不能重复使用:一旦终端操作执行后,Stream 会关闭。
  2. 并行流的不确定性parallelStream()findAny 可能返回任意元素。
  3. Optional 处理maxminfindFirst 等返回 Optional,需处理空值。
posted @ 2025-07-24 17:35  cwp0  阅读(68)  评论(0)    收藏  举报