Stream API 从入门到实践:常用操作、易错点与性能建议

Java Stream 常用中间操作与终端操作速览

一 常用中间操作

  • sorted() / sorted(Comparator) :对流元素排序,支持自然排序或自定义比较器;适用于需要有序输出的场景,如排行榜、时间线。注意排序是有状态操作,大数据量会缓存与比较开销上升。
    示例:

    java 复制代码
    List<String> words = Arrays.asList("banana","apple","cherry");
    List<String> asc = words.stream().sorted().toList();
    List<String> desc = words.stream().sorted(Comparator.reverseOrder()).toList();
  • distinct() :去除重复元素,依赖 equals/hashCode ;适用于去重后再聚合或关联。
    示例:

    java 复制代码
    List<Integer> nums = Arrays.asList(1,2,2,3,4,4,5);
    List<Integer> uniq = nums.stream().distinct().toList(); // [1,2,3,4,5]
  • limit(long n) / skip(long n) :截取前 n 个或跳过前 n 个;常与分页、抽样、Top-N 搭配。
    示例:

    java 复制代码
    List<Integer> top3 = nums.stream().limit(3).toList();
    List<Integer> after2 = nums.stream().skip(2).toList();
  • flatMap(Function<? super T, Stream<? extends R>>) :将元素映射为流并扁平化为单一流;适用于"集合的嵌套结构""一对多展开"。
    示例:

    java 复制代码
    List<List<Integer>> lists = Arrays.asList(Arrays.asList(1,2), Arrays.asList(3,4));
    List<Integer> flat = lists.stream().flatMap(List::stream).toList(); // [1,2,3,4]
  • peek(Consumer) :对每个元素执行副作用(如日志、计数),用于调试或观察流水线中间状态;注意它不保证执行时机,勿用于关键业务逻辑。
    示例:

    java 复制代码
    List<String> upper = words.stream()
        .peek(s -> System.out.println("before: "+s))
        .map(String::toUpperCase)
        .toList();
  • 原始类型流配套映射:mapToInt/mapToLong/mapToDouble、flatMapToInt/flatMapToLong/flatMapToDouble ,避免装箱拆箱,提高数值计算性能。
    示例:

    java 复制代码
    int sum = IntStream.of(1,2,3,4).sum(); // 10

    以上中间操作均为惰性,只有遇到终端操作才会触发执行。

二 常用终端操作

  • collect(Collector) :将流归约为集合、字符串或聚合结构;最常用收集器包括 toList/toSet/toMap/joining/counting/groupingBy/partitioningBy/maxBy/minBy/summingInt/averagingInt
    示例:

    java 复制代码
    List<String> list = Stream.of("a","b","c").toList();
    
    Map<String,Integer> nameLen = Stream.of("a","bb","ccc")
        .collect(Collectors.toMap(s -> s, String::length));
    
    String joined = Stream.of("a","b","c").collect(Collectors.joining(", "));
    
    Map<Integer,Long> lenCnt = Stream.of("a","bb","ccc","dd")
        .collect(Collectors.groupingBy(String::length, Collectors.counting()));
  • forEach / forEachOrdered :遍历消费元素;并行流下如需保持顺序,使用 forEachOrdered
    示例:

    java 复制代码
    words.stream().forEach(System.out::println);
    words.parallelStream().forEachOrdered(System.out::println);
  • toArray() / toArray(IntFunction) :转换为数组,适合与现有 API(如 JDBC、第三方库)对接。
    示例:

    java 复制代码
    String[] arr = words.stream().toArray(String[]::new);
  • reduce(identity, BinaryOperator) / reduce(BinaryOperator) :将流归约为单个值;适合自定义聚合(如拼接、加权合并)。
    示例:

    java 复制代码
    int sum1 = IntStream.of(1,2,3).reduce(0, Integer::sum); // 10
    Optional<Integer> sum2 = Stream.of(1,2,3).reduce(Integer::sum);
  • count() :计数;适合统计满足条件的元素数量。
    示例:

    java 复制代码
    long n = words.stream().count();
  • min(Comparator) / max(Comparator) :求最值,返回 Optional ,需提供比较器。
    示例:

    java 复制代码
    Optional<String> min = words.stream().min(String::compareTo);
  • anyMatch / allMatch / noneMatch :条件匹配,返回 boolean ;适合存在性校验、全量规则校验,具备短路特性。
    示例:

    java 复制代码
    boolean hasA = words.stream().anyMatch(s -> s.startsWith("a"));
    boolean allLen3 = words.stream().allMatch(s -> s.length() == 3);
    boolean noneEmpty = words.stream().noneMatch(String::isEmpty);
  • findFirst / findAny :查找元素,返回 Optional ;并行流下 findAny 可能返回任意一个匹配元素,findFirst 保证顺序语义。
    示例:

    java 复制代码
    Optional<String> first = words.stream().findFirst();
    Optional<String> any  = words.parallelStream().findAny();

    终端操作会触发流的实际计算,执行后流即关闭,无法再次使用。

三 选型建议与易错点

  • 操作顺序影响性能:优先 filtermap ,尽早减少数据量;必要时使用 limit/skip 做分页或截断,减少后续计算成本。
  • 有状态操作谨慎使用:sorted/distinct/limit/skip 等可能缓存或全局排序,数据量大时内存与时间开销显著。
  • 并行流与顺序语义:findAny 在并行流更"随意",需要稳定顺序或首元素语义时选 findFirst ;并行下如需顺序遍历用 forEachOrdered
  • 收集器选择:构建 Map 时注意冲突合并策略(如 toMap(k,v,(o,n)->n) );仅需要拼接用 joining ,统计用 summarizingInt 等,避免重复遍历。
  • 调试用 peek ,生产勿依赖:它不保证执行时机与次数,避免把关键业务副作用放在 peek 中。
  • 原始类型流优先:数值聚合、统计优先用 IntStream/LongStream/DoubleStream 及配套 sum/average/max/min,减少装箱与对象分配。
相关推荐
雪域迷影2 小时前
macOS系统上或首次使用Python的urllib模块时出现 ssl.SSLCertVerificationError 错误
python·macos·ssl
Knight_AL2 小时前
Java 17 新特性深度解析:记录类、密封类、模式匹配与增强的 switch 表达式对比 Java 8
java·开发语言
其美杰布-富贵-李2 小时前
PyTorch Optimizer 与 Scheduler 指南
人工智能·pytorch·python·优化·训练
吴佳浩 Alben2 小时前
Go 1.25.5 通关讲解
开发语言·后端·golang
XXYBMOOO2 小时前
理解 C++ 中的字节序转换函数 `swapEndian`
开发语言·arm开发·c++
小高Baby@2 小时前
深入理解golang的GMP模型
开发语言·后端·golang
a努力。2 小时前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·面试
毕加锁2 小时前
深度解析昇腾Catlass:C++模板元编程与高性能算子开发范式(1)
开发语言·c++
Franklin2 小时前
如何解决git HEAD detached 分离头指针问题
git·python·pycharm