当前位置: 首页 > news >正文

Java 8 的流(Stream API)简介

Java 8 引入的 Stream API 是一个强大的工具,用于处理集合(如 List、Set)中的元素。它支持各种操作,包括过滤、排序、映射等,并且能够以声明式的方式表达复杂的查询操作。流操作可以是中间操作(返回流以便进一步处理)或终端操作(产生结果或副作用)。此外,Stream API 还支持并行执行,从而利用多核处理器的优势。

Stream 的基本概念


  • 任何提供数据的集合(如 ListSet、数组等)均可作为流的来源。

  • 中间操作
    返回新流对象,支持链式调用,惰性求值。常见操作包括:

    • filter(筛选)
    • map(映射)
    • sorted(排序)
    • distinct(去重)
    • limit(限制数量)
    • skip(跳过元素)
    • flatMap(扁平化映射)
    • peek(调试查看)
  • 终端操作
    触发流处理并生成结果,执行后流被消耗。常见操作包括:

    • forEach(遍历)
    • collect(收集到集合)
    • reduce(聚合)
    • count(统计数量)
    • findFirst/findAny(查找元素)
    • anyMatch/allMatch/noneMatch(匹配验证)

创建 Stream 的方式

  1. 从集合创建

    List<String> list = Arrays.asList("apple", "banana", "pear");
    Stream<String> stream = list.stream();
  2. 从数组创建

    String[] arr = {"apple", "banana", "pear"};
    Stream<String> stream = Arrays.stream(arr);
  3. 生成无限流

    // 迭代生成(0, 1, 2, ...)
    Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);// 随机生成
    Stream<Double> randomStream = Stream.generate(Math::random);

中间操作详解

1. 筛选与切片

  • filter:按条件筛选元素

    List<String> filtered = list.stream().filter(s -> s.length() > 3).collect(Collectors.toList());
  • distinct:去重(需重写 equals 和 hashCode

    List<Integer> distinctList = Arrays.asList(1, 2, 2, 3).stream().distinct().collect(Collectors.toList()); // [1, 2, 3]
  • limit:截取前 N 个元素

    List<String> firstTwo = list.stream().limit(2).collect(Collectors.toList());
  • skip:跳过前 N 个元素

    List<String> skipped = list.stream().skip(1).collect(Collectors.toList());

2. 映射与扁平化

  • map:元素类型转换

    List<String> upperCase = list.stream().map(String::toUpperCase).collect(Collectors.toList());
  • flatMap:扁平化嵌套集合

    List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2),Arrays.asList(3, 4)
    );
    List<Integer> flatList = nestedList.stream().flatMap(List::stream).collect(Collectors.toList()); // [1, 2, 3, 4]

3. 排序

  • 自然排序

    List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
  • 自定义排序

    List<Employee> sortedEmployees = employees.stream().sorted((e1, e2) -> e2.getAge() - e1.getAge()).collect(Collectors.toList());

4. 调试查看

  • peek:遍历元素时执行操作(如打印)
    list.stream().peek(System.out::println).collect(Collectors.toList());

终端操作详解

1. 收集结果

  • 收集到集合

    List<String> listResult = Stream.of("a", "b", "c").collect(Collectors.toList());Set<String> setResult = Stream.of("apple", "banana", "pear").collect(Collectors.toSet());
  • 分组与分区

    Map<Integer, List<String>> grouped = list.stream().collect(Collectors.groupingBy(s -> s.length()));

2. 聚合操作

  • reduce 求和

    int sum = numbers.stream().reduce(0, (a, b) -> a + b);
  • 拼接字符串

    String joined = Stream.of("a", "b", "c").reduce("", (a, b) -> a + b); // "abc"
  • 无初始值的聚合

    Optional<Integer> max = numbers.stream().reduce(Integer::max);

3. 查找与匹配

  • findFirst:获取第一个元素

    Optional<String> first = list.stream().filter(s -> s.startsWith("a")).findFirst();
  • findAny:获取任意元素(并行流中可能乱序)

    Optional<String> any = list.parallelStream().findAny();
  • max/min:获取极值

    Optional<Integer> maxNumber = numbers.stream().max(Integer::compare);

4. 匹配验证

  • anyMatch:至少一个元素满足条件

    boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
  • allMatch:所有元素满足条件

    boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);
  • noneMatch:无元素满足条件

    boolean noEven = numbers.stream().noneMatch(n -> n % 2 == 0);

5. 统计与转换

  • count:统计元素数量

    long count = list.stream().filter(s -> s.length() > 3).count();
  • toArray:转换为数组

    String[] array = list.stream().toArray(String[]::new);
  • 数值统计

    IntSummaryStatistics stats = numbers.stream().mapToInt(Integer::intValue).summaryStatistics();
    System.out.println(stats.getAverage()); // 平均值

6. 遍历操作

  • forEach:执行副作用操作
    list.stream().forEach(System.out::println);

并行流(Parallel Stream)

  • 启用并行流

    List<String> list = Arrays.asList("apple", "banana", "pear");
    list.parallelStream().forEach(System.out::println);
  • 注意事项

    • 并行流可能提高大数据集处理性能。
    • 需确保线程安全性(如避免共享状态修改)。
    • 并行排序(sorted())可能不稳定,需谨慎使用。

注意事项

  1. 中间操作顺序
    逻辑顺序需合理(如先 filter 再 map)。

  2. 对象去重
    使用 distinct() 时需重写 hashCode() 和 equals()

  3. 流复用问题
    终端操作后流被消耗,需重新创建流:

    Stream<String> stream = list.stream();
    stream.forEach(System.out::println); // 首次使用
    stream.forEach(System.out::println); // 报错!流已关闭
  4. 安全获取值
    使用 Optional 的 orElse()orElseGet() 或 orElseThrow() 避免空指针。

总结

Java 8 Stream API 通过声明式编程简化了集合操作,支持链式调用和并行处理。合理使用中间操作(如 filtermap)和终端操作(如 collectreduce),可高效完成数据聚合、过滤及验证。结合并行流可显著提升大数据集处理性能,但需注意线程安全性和操作顺序。


http://www.mrgr.cn/news/96868.html

相关文章:

  • JavaScript instanceof 运算符全解析
  • 蓝桥杯省模拟赛 数位和
  • Linux: 进程信号初识
  • STL 性能优化实战:解决项目中标准模板库的性能瓶颈
  • windows部署docker
  • 第1章-3 MySQL的逻辑架构
  • py数据结构day3
  • java 使用 spring AI 实战MCP
  • es自定义ik分词器中文词库实现热更新
  • java项目分享-分布式电商项目附软件链接
  • C++ 新特性 | C++ 11 | 左值、右值与将亡值
  • Windows 实战-evtx 文件分析--笔记
  • 1.4 基于模拟退火改进蛇算法优化VGG13SE网络超参数的故障诊断模型
  • VMware上的windows虚拟机安装使用Docker方法
  • 3D 地图渲染-区域纹理图添加
  • C++中的继承
  • 推导Bias² + Variance + σ²_ε
  • 【11408学习记录】从混乱到清晰:还原+断开+简化,彻底攻破英语分裂式长难句
  • Spring Boot 工程创建详解
  • arcgis10.8 Toolbox中没有找到conversion tools模块