当前位置: 首页 > 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.dtcms.com/a/108120.html

相关文章:

  • 链表(单链表、双链表、循环链表、静态链表)入门
  • Mybatis Plus扩展方法与Pagehelper分页插件
  • 2021-07-05 C#定义一个1到100的数组,用lambda表达式查出尾数是8的数字
  • 瑞昱RTD2556QR显示器驱动芯片
  • ES使用聚合aggregations实战(自用:2025.04.03更新)
  • 机器学习与深度学习3、神经网络原理
  • 子组件使用:visible.sync=“visible“进行双向的绑定导致该弹窗与其他弹窗同时显示的问题
  • 【数据结构】双向链表
  • Spring / Spring Boot 的@MapperScan 和 @Repository
  • Java 可变参数全解析:动态参数传递的实践指南
  • 【MySQL基础-20】MySQL条件函数全面解析:提升查询逻辑的利器
  • 区块链技术如何重塑金融衍生品市场?
  • 防火墙(RHCE)
  • 大数据:信息时代的黄金矿藏
  • Leetcode 合集 -- 排列问题 | 递归
  • k8s statefulset pod重启顺序
  • Qt 读写锁QReadWriteLock
  • 前端计算机网络常问问题大全
  • 如何在服务器端配置SSH以允许密码认证
  • html5炫酷图片悬停效果实现详解
  • 【零基础入门unity游戏开发——2D篇】使用SpriteAtlas(精灵图集)打包图集,减少DrawCall提高性能
  • 第四章、Isaacsim在GUI中构建机器人(1): 添加简单对象
  • SQL复杂查询与性能优化:医药行业ERP系统实战指南
  • Linux 基础入门操作 第九章 进程间通信之有名管道
  • el-select+el-tree、el-select+vl-tree实现下拉树形选择
  • Linux中进程与计划任务
  • SpringMvc获取请求数据
  • HTML5 Canvas绘画板项目实战:打造一个功能丰富的在线画板
  • 配置 UOS/deepin 系统远程桌面,实现多台电脑协同办公
  • PHP 8.x:现代Web开发的性能与效率革命