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

【Stream API学习】

Stream API学习

  • 一、 什么是 Stream?
  • 二、Stream 操作的三个步骤
  • 三、详细操作说明
    • 1. 创建 Stream
    • 2. 中间操作(Intermediate Operations)
    • 3. 终端操作(Terminal Operations)
  • 四、核心代码示例
    • 示例1:找出低卡路里(<400)的菜品名称,并按卡路里排序
    • 示例2:统计菜单中有多少种肉菜
    • 示例3:使用 flatMap 处理嵌套集合
    • 示例4:使用 reduce 求和
  • 五、并行流(Parallel Stream)
  • 六、总结与最佳实践

一、 什么是 Stream?

你可以把 Stream 想象成一个高级的迭代器(Iterator),但它更强大。它代表的是一个数据序列,这个序列支持顺序和并行的聚合操作。

核心思想:不是直接操作数据,而是描述对数据做什么。例如,“找出所有大于10的数,然后排序,最后打印出来”。这种风格叫声明式编程(告诉计算机“做什么”),区别于传统的命令式编程(告诉计算机“怎么做”)。

主要特点:

  1. 不是数据结构:它自己不存储数据,数据来自数据源(如集合、数组、I/O通道)。

  2. 函数式风格:对流的操作会产生一个结果,但不会修改其底层的数据源。

  3. 惰性执行:很多中间操作(如 filter, map)是惰性的,只有遇到终端操作时,整个操作链才会被执行。

  4. 可消费性:每个 Stream 只能被“消费”一次。一旦调用了终端操作,流就关闭了,不能再使用。

二、Stream 操作的三个步骤

使用 Stream 通常包含三个步骤:

  1. 创建 Stream:从一个数据源(如集合)获取一个流。

  2. 中间操作:对数据进行处理/转换(如过滤、映射、排序),返回一个新的 Stream,可以连续操作。

  3. 终端操作:执行操作链,并产生结果。执行后,该流就不能再被使用。

流程:数据源 -> 创建流 -> 中间操作1 -> 中间操作2 -> … -> 终端操作 -> 结果

三、详细操作说明

1. 创建 Stream

方法描述示例
collection.stream()最常用的方式,从集合创建顺序流list.stream()
collection.parallelStream()创建并行流,可利用多核优势list.parallelStream()
Arrays.stream(T[] array)从数组创建流Arrays.stream(new int[]{1,2,3})
Stream.of(T… values)直接传入一系列值创建流Stream.of(“a”, “b”, “c”)
Stream.iterate()生成无限流(需用 limit 限制)Stream.iterate(0, n -> n+2)
Stream.generate()通过 Supplier 生成无限流Stream.generate(Math::random)

2. 中间操作(Intermediate Operations)

重要:中间操作是惰性的,不遇到终端操作不会执行。

操作描述示例
filter(Predicate)过滤,保留满足条件的元素.filter(s -> s.length() > 3)
map(Function<T, R>)映射,将元素转换成其他形式或提取信息.map(String::toUpperCase)
flatMap(Function<T, Stream>)扁平化映射,将每个元素转换成一个流,然后把所有流连接起来.flatMap(list -> list.stream())
distinct()去重,根据 equals() 方法去重.distinct()
sorted() / sorted(Comparator)排序.sorted() / .sorted(Comparator.reverseOrder())
limit(long maxSize)限制,截断流,使其元素不超过给定数量.limit(10)
skip(long n)跳过,跳过前 n 个元素.skip(5)
peek(Consumer)“窥视”,对每个元素执行操作,主要用于调试.peek(System.out::println)

3. 终端操作(Terminal Operations)

执行后,流管道被消费,无法再使用。

操作描述示例返回类型
forEach(Consumer)遍历,对每个元素执行操作.forEach(System.out::println)void
collect(Collector)收集,将流转换为其他形式(如 List, Set, Map).collect(Collectors.toList())集合等
toArray()转为数组.toArray()Object[]
reduce(…)归约,将流中元素反复结合,得到一个值.reduce(0, Integer::sum)Optional 或 T
min(Comparator) / max(Comparator)求最小值/最大值.min(Comparator.naturalOrder())Optional
count()计数,返回流中元素个数.count()long
anyMatch(Predicate)任意匹配,检查是否至少有一个元素匹配.anyMatch(s -> s.startsWith(“A”))boolean
allMatch(Predicate)全部匹配.allMatch(s -> s.length() > 0)boolean
noneMatch(Predicate)没有匹配.noneMatch(s -> s.isEmpty())boolean
findFirst()返回第一个元素.findFirst()Optional
findAny()返回任意一个元素(在并行流中效率更高).findAny()Optional

四、核心代码示例

让我们通过一些例子来加深理解。
假设有一个 Dish 类和一个菜单列表:

public class Dish {private final String name;private final boolean vegetarian;private final int calories;private final Type type;// 构造器、getter、toString 省略public enum Type { MEAT, FISH, OTHER }
}List<Dish> menu = Arrays.asList(new Dish("pork", false, 800, Dish.Type.MEAT),new Dish("beef", false, 700, Dish.Type.MEAT),new Dish("chicken", false, 400, Dish.Type.MEAT),new Dish("french fries", true, 530, Dish.Type.OTHER),new Dish("rice", true, 350, Dish.Type.OTHER),new Dish("season fruit", true, 120, Dish.Type.OTHER),new Dish("pizza", true, 550, Dish.Type.OTHER),new Dish("prawns", false, 300, Dish.Type.FISH),new Dish("salmon", false, 450, Dish.Type.FISH)
);

示例1:找出低卡路里(<400)的菜品名称,并按卡路里排序

List<String> lowCaloricDishesName = menu.stream() // 1. 获取流.filter(d -> d.getCalories() < 400)      // 2. 中间操作:过滤.sorted(Comparator.comparing(Dish::getCalories)) // 中间操作:排序.map(Dish::getName)                      // 中间操作:映射,提取菜名.collect(Collectors.toList());           // 3. 终端操作:收集为ListSystem.out.println(lowCaloricDishesName); 
// 输出:[season fruit, prawns, rice]

示例2:统计菜单中有多少种肉菜

long count = menu.stream().filter(d -> d.getType() == Dish.Type.MEAT).count();
System.out.println("肉菜种类: " + count); 
// 输出:肉菜种类: 3

示例3:使用 flatMap 处理嵌套集合

假设有一个 List<List>,我们想找出所有不重复的字母。

List<List<String>> listOfLists = Arrays.asList(Arrays.asList("apple", "banana"),Arrays.asList("orange", "grape", "kiwi")
);List<String> uniqueLetters = listOfLists.stream().flatMap(List::stream) // 将每个List<String>扁平化为一个String流.map(word -> word.split("")) // 将每个单词映射成字母数组 Stream<String[]>.flatMap(Arrays::stream)     // 将每个数组扁平化为一个字母流 Stream<String>.distinct().collect(Collectors.toList());System.out.println(uniqueLetters);
// 输出:[a, p, l, e, b, n, o, r, g, k, i, w]

示例4:使用 reduce 求和

// 计算所有菜品的总卡路里
int totalCalories = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum); // 0是初始值,Integer::sum是累加器
// 等同于 .reduce(0, (a, b) -> a + b);System.out.println("总卡路里: " + totalCalories);

五、并行流(Parallel Stream)

Stream API 简化了并行编程。只需将 .stream() 换成 .parallelStream(),或者对已有流调用 .parallel() 方法,框架会自动帮你将任务分解到多个线程上执行。

// 顺序流
long count1 = menu.stream().filter(Dish::isVegetarian).count();// 并行流
long count2 = menu.parallelStream().filter(Dish::isVegetarian).count();

注意事项:

  • 状态无关:确保传递给流操作(如 filter, map)的函数是无状态的,不依赖或修改外部可变状态,否则并行时会产生错误。

  • 开销:并行化本身有开销(线程创建、通信、结果合并),对于小数据量或简单操作,顺序流可能更快。

  • 可拆分性:数据源是否易于分割(如 ArrayList 比 LinkedList 更容易并行)。

六、总结与最佳实践

  1. 优先使用声明式风格:代码更简洁、易读、易维护。

  2. 理解惰性求值:中间操作不触发实际计算,这允许进行优化(如短路、循环合并)。

  3. 合理使用并行流:对于大数据集且计算密集型的任务,考虑使用并行流。先测试,再决定。

  4. 熟悉 Collectors 工具类:它提供了非常多强大的收集器,如分组(groupingBy)、分区(partitioningBy)、连接字符串(joining)等,是 Stream 的利器。

Stream API 是现代 Java 编程的基石,熟练掌握它能极大提升你的开发效率和代码质量。建议多动手练习,体会其思想。

http://www.dtcms.com/a/399516.html

相关文章:

  • 怎样下载建设银行信用卡网站蓝色科技企业网站模板免费下载
  • ubuntu16安装python3.12
  • 编辑网站教程阜宁县城乡建设局新的官方网站
  • 禅城区做网站策划企业公示信息填报
  • LSTM:长短期记忆网络的原理、演进与应用
  • OpenHarmony 4.0 Release横屏配置
  • 网站开发前端与后端铁汉生态建设有限公司网站
  • 服务器安全基线配置
  • 随机森林算法详解:从原理到实战
  • 数据库回表查询解析:从原理到实战优化
  • 详解单元测试、集成测试、系统测试
  • 企业网站设计要点郑州seo哪家公司最强
  • 互动网站制作wordpress add option
  • wordpress 上传 重命名郑州seo外包平台
  • 【C++实战㊱】解锁C++依赖倒置:从理论到实战的蜕变之旅
  • 项目案例作业2:对案例进行面向对象分析
  • 锤子助手插件功能七十二:对话内图片「一键添加至表情」
  • 饮食网站开发需求网站开发 面试
  • Deepseek本地部署教程模型怎么选择?按需选择让效率翻倍
  • 企业备案网站服务内容wordpress ajax搜索
  • 自己做网站不推广备案可以不关闭网站吗
  • 12_OkHttp初体验
  • 硅基计划5.0 MySQL 壹 初识MySQL
  • 网站规划建设方案免费微信点餐小程序
  • Ford-Fulkerson最大流算法数学原理详解
  • 湛江做寄生虫网站wordpress修改端口
  • 从技术角度分析 “诺亚参数” 生成式设计工具
  • 做pc端网站代理商广告传媒网站模板
  • All In AI之三:一文构建Python核心语法体系
  • 湖州公司做网站南山龙岗最新通告