0

0

Java中Stream的用法_Java中Stream的操作指南

冰火之心

冰火之心

发布时间:2025-06-29 21:15:02

|

686人浏览过

|

来源于php中文网

原创

stream是java 8引入的声明式数据处理特性,通过中间操作和终端操作简化集合处理。1. 创建方式包括:从集合调用stream()或parallelstream();2. 使用arrays.stream()转换数组;3. stream.of()直接传元素;4. generate()生成无限流需配合limit();5. iterate()创建有序无限流也需limit()。常用中间操作有filter过滤、map映射、flatmap展平嵌套结构、distinct去重、sorted排序、peek调试、limit截断、skip跳过。终端操作如foreach遍历、toarray转数组、reduce归约、collect收集结果、min/max找极值、count计数、anymatch/allmatch/nonematch判断匹配、findfirst/findany获取元素。适合使用并行流的场景包括大数据量、复杂计算、无依赖数据、cpu密集型任务且需线程安全。与传统循环相比,stream为声明式、内部迭代更简洁并支持并行处理。

Java中Stream的用法_Java中Stream的操作指南

Stream是Java 8引入的一个强大的特性,它允许你以声明式的方式处理集合数据,简化代码并提高效率。可以把它看作是数据流,你可以在上面执行各种操作,例如过滤、映射、排序等,最终得到想要的结果。

Java中Stream的用法_Java中Stream的操作指南

Stream的操作可以分为两种:中间操作和终端操作。中间操作返回一个新的Stream,允许你链式调用多个操作。终端操作则会消费Stream,产生一个结果或副作用。

Java中Stream的用法_Java中Stream的操作指南

如何创建Stream?

创建Stream的方法有很多,最常见的几种方式包括:

立即学习Java免费学习笔记(深入)”;

Java中Stream的用法_Java中Stream的操作指南
  1. 从集合创建: 这是最常用的方式,直接调用Collection接口的stream()parallelStream()方法即可。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    Stream stream = names.stream(); // 创建顺序流
    Stream parallelStream = names.parallelStream(); // 创建并行流
  2. 从数组创建: 使用Arrays.stream()方法可以将数组转换为Stream。

    int[] numbers = {1, 2, 3, 4, 5};
    IntStream stream = Arrays.stream(numbers);
  3. 使用Stream.of()方法: 可以直接将多个元素作为参数传递给Stream.of()方法来创建Stream。

    Stream stream = Stream.of("Apple", "Banana", "Orange");
  4. 使用Stream.generate()方法: 可以使用Stream.generate()方法生成一个无限流,需要提供一个Supplier函数来生成元素。注意: 无限流需要配合limit()方法来限制流的大小,否则会无限循环。

    Stream randomStream = Stream.generate(Math::random).limit(10); // 生成10个随机数的流
  5. 使用Stream.iterate()方法: 可以使用Stream.iterate()方法生成一个有序的无限流,需要提供一个初始值和一个UnaryOperator函数来生成后续元素。同样,需要配合limit()方法来限制流的大小。

    Stream evenNumbers = Stream.iterate(0, n -> n + 2).limit(10); // 生成10个偶数的流

Stream的常用中间操作有哪些?

中间操作会返回一个新的Stream,允许你链式调用多个操作,对数据进行转换和过滤。常见的中间操作包括:

  1. filter(Predicate predicate): 过滤Stream中的元素,只保留满足predicate条件的元素。

    List names = Arrays.asList("Alice", "Bob", "Charlie", "Anna");
    Stream filteredStream = names.stream().filter(name -> name.startsWith("A")); // 过滤出以"A"开头的名字
  2. map(Function mapper): 将Stream中的每个元素映射为另一个元素,可以使用mapper函数进行转换。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    Stream nameLengths = names.stream().map(String::length); // 将名字映射为名字的长度
  3. flatMap(Function> mapper): 将Stream中的每个元素映射为一个Stream,然后将所有Stream连接成一个Stream。这个操作通常用于处理嵌套的集合。想象一下,你有一个List>,你想把它变成一个List,flatMap就派上用场了。

    List> nestedList = Arrays.asList(
            Arrays.asList("a", "b"),
            Arrays.asList("c", "d", "e")
    );
    Stream flattenedStream = nestedList.stream().flatMap(List::stream); // 将嵌套的List展平
  4. distinct(): 去除Stream中重复的元素。

    List numbers = Arrays.asList(1, 2, 2, 3, 3, 3);
    Stream distinctStream = numbers.stream().distinct(); // 去除重复的数字
  5. sorted(): 对Stream中的元素进行排序。可以传入Comparator来自定义排序规则。

    List names = Arrays.asList("Charlie", "Alice", "Bob");
    Stream sortedStream = names.stream().sorted(); // 默认按字母顺序排序
    Stream sortedStreamByLength = names.stream().sorted(Comparator.comparingInt(String::length)); // 按名字长度排序
  6. peek(Consumer action): 对Stream中的每个元素执行action操作,但不会改变Stream的内容。这个操作通常用于调试,可以在Stream处理过程中查看元素的值。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    Stream peekedStream = names.stream().peek(System.out::println); // 打印每个名字
  7. limit(long maxSize): 截断Stream,只保留前maxSize个元素。

    Stream numbers = Stream.iterate(1, n -> n + 1);
    Stream limitedStream = numbers.limit(10); // 只保留前10个数字
  8. skip(long n): 跳过Stream中的前n个元素。

    方正魏碑简体
    方正魏碑简体

    魏碑是指南北朝时期北朝的碑刻书法作品。现存的魏碑书体都是楷书,因此有时也把这些楷书碑刻作品称为“魏楷”。魏碑原本也称北碑,在北朝相继的各个王朝中以北魏的立国时间最长,后来就用“魏碑”来指称包括东魏、西魏、北齐和北周在内的整个北朝的碑刻书法作品。这些碑刻作品主要是以“石碑”、“墓志铭”、“ 摩崖”和“造像记”的形式存在的。 构扁方疏朗,内紧外松,多出隶意。此墓志虽属正书,行笔却不拘一格,风骨内敛,自

    下载
    Stream numbers = Stream.iterate(1, n -> n + 1);
    Stream skippedStream = numbers.skip(5); // 跳过前5个数字

Stream的常用终端操作有哪些?

终端操作会消费Stream,产生一个结果或副作用。常见的终端操作包括:

  1. forEach(Consumer action): 对Stream中的每个元素执行action操作。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    names.stream().forEach(System.out::println); // 打印每个名字
  2. toArray(): 将Stream中的元素转换为数组。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    String[] nameArray = names.stream().toArray(String[]::new); // 转换为String数组
  3. reduce(BinaryOperator accumulator): 将Stream中的元素归约为一个值。可以提供一个初始值,也可以不提供。

    List numbers = Arrays.asList(1, 2, 3, 4, 5);
    int sum = numbers.stream().reduce(0, Integer::sum); // 计算所有数字的和,初始值为0
    Optional product = numbers.stream().reduce(Integer::sum); // 计算所有数字的积,没有初始值,返回Optional
  4. collect(Collector collector): 将Stream中的元素收集到集合中。可以使用Collectors类提供的各种收集器,例如toList()toSet()toMap()等。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    List nameList = names.stream().collect(Collectors.toList()); // 收集到List
    Set nameSet = names.stream().collect(Collectors.toSet()); // 收集到Set
    Map nameMap = names.stream().collect(Collectors.toMap(name -> name, String::length)); // 收集到Map,key为名字,value为名字的长度
  5. min(Comparator comparator): 返回Stream中的最小值。需要提供一个Comparator来比较元素。

    List numbers = Arrays.asList(5, 2, 8, 1, 9);
    Optional min = numbers.stream().min(Integer::compare); // 找到最小的数字
  6. max(Comparator comparator): 返回Stream中的最大值。需要提供一个Comparator来比较元素。

    List numbers = Arrays.asList(5, 2, 8, 1, 9);
    Optional max = numbers.stream().max(Integer::compare); // 找到最大的数字
  7. count(): 返回Stream中元素的个数。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    long count = names.stream().count(); // 计算名字的个数
  8. anyMatch(Predicate predicate): 判断Stream中是否存在任意一个元素满足predicate条件。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    boolean anyMatch = names.stream().anyMatch(name -> name.startsWith("A")); // 是否存在以"A"开头的名字
  9. allMatch(Predicate predicate): 判断Stream中是否所有元素都满足predicate条件。

    List names = Arrays.asList("Alice", "Anna", "Amy");
    boolean allMatch = names.stream().allMatch(name -> name.startsWith("A")); // 是否所有名字都以"A"开头
  10. noneMatch(Predicate predicate): 判断Stream中是否没有元素满足predicate条件。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    boolean noneMatch = names.stream().noneMatch(name -> name.startsWith("Z")); // 是否没有名字以"Z"开头
  11. findFirst(): 返回Stream中的第一个元素。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    Optional first = names.stream().findFirst(); // 找到第一个名字
  12. findAny(): 返回Stream中的任意一个元素。在并行流中,findAny()的效率通常比findFirst()更高。

    List names = Arrays.asList("Alice", "Bob", "Charlie");
    Optional any = names.parallelStream().findAny(); // 找到任意一个名字

什么时候应该使用并行流?

并行流可以利用多核CPU的优势,提高处理数据的效率。但是,并行流并非总是最佳选择。以下是一些需要考虑的因素:

  • 数据量: 当数据量足够大时,并行流才能体现出优势。对于小数据量,并行流的开销可能超过其带来的性能提升。
  • 操作的复杂性: 对于简单的操作,并行流的优势可能不明显。对于复杂的操作,并行流可以显著提高效率。
  • 数据之间的依赖性: 如果数据之间存在依赖性,并行流可能会导致错误的结果。
  • CPU密集型操作: 并行流更适合CPU密集型操作,例如计算、排序等。对于IO密集型操作,并行流的优势可能不明显。
  • 线程安全: 使用并行流时,需要确保操作是线程安全的。

一般来说,当数据量较大,操作比较复杂,且数据之间没有依赖性时,可以考虑使用并行流。

Stream和传统循环有什么区别

Stream和传统循环的主要区别在于:

  • 声明式 vs 命令式: Stream采用声明式编程,你只需要描述你想做什么,而不需要关心如何实现。传统循环采用命令式编程,你需要明确地指定每一步的操作。
  • 内部迭代 vs 外部迭代: Stream采用内部迭代,由Stream API负责迭代数据。传统循环采用外部迭代,你需要自己控制迭代过程。
  • 代码简洁性: Stream可以简化代码,使代码更易读易懂。
  • 并行处理: Stream可以方便地进行并行处理,提高效率。

总的来说,Stream提供了一种更简洁、更高效的数据处理方式。在合适的场景下,使用Stream可以显著提高代码的可读性和性能。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

841

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

737

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

相关下载

更多

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++教程
C++教程

共115课时 | 13万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号