Java中如何用Stream对集合进行过滤和映射

雨辰小哥_5416

雨辰小哥_5416

2025-06-12

571人浏览

原创

java stream 是一种声明式处理集合的方式,通过操作链实现数据过滤、转换等。其核心思想是将数据源如 list、set 转换为 stream,接着使用 filter() 方法接收 predicate 接口以判断元素是否保留来过滤数据,如用 n -> n > 10 过滤出大于 10 的数字;随后可调用 map() 方法接收 function 接口以转换元素,如 string::touppercase 将字符串转为大写;这些中间操作具备延迟执行特性,只有终端操作如 collect()、foreach()、sum() 等被调用时才执行,且可并行处理,通过 parallelstream() 分解任务提升性能,但需评估线程开销;此外,stream 只能使用一次,消耗后需重新创建;异常处理可通过 try-catch 捕获或 optional 类型安全处理 null 值,确保流操作的健壮性。

Java中如何用Stream对集合进行过滤和映射

Java Stream提供了一种声明式的方式来处理集合数据,核心在于通过一系列操作链,实现数据的过滤、转换等。简单来说,就是把集合变成一个“流”,然后像流水线一样加工它。

Java中如何用Stream对集合进行过滤和映射

解决方案

Java中如何用Stream对集合进行过滤和映射

Java Stream API 允许你以函数式风格对集合进行过滤和映射。其核心思想是将数据源(如 List、Set 等)转换为 Stream,然后应用一系列中间操作(如 filter、map)来转换数据,最后通过终端操作(如 collect、forEach)来产生结果。

Java中如何用Stream对集合进行过滤和映射

如何使用 Stream 进行过滤?

过滤操作 filter() 接收一个 Predicate 函数式接口,该接口定义了一个 test() 方法,用于判断元素是否应该被包含在结果流中。

例如,假设你有一个整数列表,想要过滤出所有大于 10 的数字:

List<integer> numbers = Arrays.asList(1, 5, 12, 8, 15, 3);

List<integer> filteredNumbers = numbers.stream()
                                        .filter(n -> n > 10)
                                        .collect(Collectors.toList());

System.out.println(filteredNumbers); // 输出: [12, 15]</integer></integer>

这里,n -> n > 10 就是一个 Predicate 表达式,它判断数字 n 是否大于 10。collect(Collectors.toList()) 则是将过滤后的 Stream 转换回 List。

如何使用 Stream 进行映射?

映射操作 map() 接收一个 Function 函数式接口,该接口定义了一个 apply() 方法,用于将一个元素转换为另一个元素。

例如,假设你有一个字符串列表,想要将每个字符串转换为大写:

List<string> names = Arrays.asList("Alice", "Bob", "Charlie");

List<string> upperCaseNames = names.stream()
                                   .map(String::toUpperCase)
                                   .collect(Collectors.toList());

System.out.println(upperCaseNames); // 输出: [ALICE, BOB, CHARLIE]</string></string>

String::toUpperCase 是一个方法引用,它等价于 s -> s.toUpperCase(),将字符串 s 转换为大写。

如何同时进行过滤和映射?

你可以将 filter()map() 操作链式调用,先过滤再映射,或者先映射再过滤,取决于你的需求。

例如,假设你有一个 Person 对象列表,想要获取所有年龄大于 20 岁的人的名字,并将名字转换为大写:

class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

List<person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 18),
    new Person("Charlie", 30)
);

List<string> upperCaseNames = people.stream()
                                     .filter(p -> p.getAge() > 20)
                                     .map(Person::getName)
                                     .map(String::toUpperCase)
                                     .collect(Collectors.toList());

System.out.println(upperCaseNames); // 输出: [ALICE, CHARLIE]</string></person>

这里,我们先使用 filter() 过滤出年龄大于 20 岁的人,然后使用 map() 获取他们的名字,再使用 map() 将名字转换为大写。

Stream 的延迟执行特性是什么?

Stream 的一个重要特性是延迟执行(Lazy Evaluation)。中间操作(如 filter()map())不会立即执行,而是会等到终端操作(如 collect())被调用时才一起执行。

Upload audio to AIOZ Stream
Upload audio to AIOZ Stream

快速上传音频至 AIOZ Stream API。支持默认或自定义编码配置创建音频对象,上传文件并完成处理后返回音频链接。

下载

这种延迟执行的特性可以提高性能,因为 Stream 可以避免不必要的计算。例如,如果你的 Stream 只需要处理前几个元素,那么 Stream 可以只计算前几个元素,而不需要计算整个集合。

Stream 可以并行处理吗?

Stream 可以通过调用 parallelStream() 方法来并行处理。并行处理可以将任务分解成多个子任务,并在多个线程上同时执行,从而提高处理速度。

例如,假设你想要计算一个大型数字列表中所有大于 10 的数字的总和:

List<integer> numbers = new ArrayList();
for (int i = 0; i  n > 10)
                 .mapToInt(Integer::intValue)
                 .sum();

System.out.println(sum);</integer>

这里,我们使用 parallelStream() 创建一个并行 Stream,然后使用 filter() 过滤出大于 10 的数字,再使用 mapToInt() 将 Integer 对象转换为 int 类型,最后使用 sum() 计算总和。

需要注意的是,并行处理并非总是能提高性能。如果任务过于简单,或者数据量太小,并行处理可能会因为线程切换的开销而降低性能。因此,在使用并行 Stream 之前,需要仔细评估其性能影响。

Stream 只能使用一次吗?

是的,Stream 只能使用一次。一旦你对 Stream 执行了终端操作,Stream 就被“消耗”掉了,不能再次使用。如果你需要再次使用相同的数据,你需要重新创建一个新的 Stream。这其实也符合“流”的概念,用完就没了。

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

除了 collect()forEach()sum() 之外,Stream 还有很多其他常用的终端操作,例如:

  • count(): 统计 Stream 中元素的数量。
  • min(): 找出 Stream 中最小的元素。
  • max(): 找出 Stream 中最大的元素。
  • findFirst(): 找出 Stream 中第一个元素。
  • findAny(): 找出 Stream 中任意一个元素。
  • anyMatch(): 判断 Stream 中是否存在至少一个元素满足指定条件。
  • allMatch(): 判断 Stream 中是否所有元素都满足指定条件。
  • noneMatch(): 判断 Stream 中是否没有任何元素满足指定条件。
  • reduce(): 将 Stream 中的元素聚合为一个结果。

这些终端操作可以满足各种不同的需求,你可以根据实际情况选择合适的终端操作。

Stream 的异常处理应该如何进行?

在 Stream 操作中,如果某个操作抛出异常,整个 Stream 流程将会中断。为了避免这种情况,你需要对 Stream 操作进行异常处理。

一种常见的做法是使用 try-catch 块来捕获异常,并在 catch 块中进行处理。例如:

List<string> names = Arrays.asList("Alice", "Bob", "Charlie", null);

names.stream()
     .map(name -> {
         try {
             return name.toUpperCase();
         } catch (NullPointerException e) {
             System.err.println("遇到空指针异常: " + e.getMessage());
             return null; // 或者返回一个默认值
         }
     })
     .filter(Objects::nonNull) // 过滤掉 null 值
     .forEach(System.out::println);</string>

在这个例子中,我们使用 try-catch 块来捕获 NullPointerException 异常,并在 catch 块中打印错误信息,然后返回 null 值。最后,我们使用 filter(Objects::nonNull) 来过滤掉 null 值。

另一种做法是使用 Optional 来处理可能为空的值。例如:

List<string> names = Arrays.asList("Alice", "Bob", "Charlie", null);

names.stream()
     .map(name -> Optional.ofNullable(name)
                          .map(String::toUpperCase)
                          .orElse(null))
     .filter(Objects::nonNull)
     .forEach(System.out::println);</string>

在这个例子中,我们使用 Optional.ofNullable(name)name 转换为 Optional 对象。如果 namenull,则 Optional 对象为空。然后,我们使用 map(String::toUpperCase)Optional 对象中的字符串转换为大写。如果 Optional 对象为空,则 map() 方法不会执行。最后,我们使用 orElse(null) 来返回 Optional 对象中的值,如果 Optional 对象为空,则返回 null

总而言之,Java Stream 是一种强大的工具,可以让你以简洁、高效的方式处理集合数据。掌握 Stream API 的使用方法,可以大大提高你的编程效率。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java stream

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

4999

3

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

509

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1638

6

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.20

2248

5

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

2025.12.04

678

13

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1518

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2164

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

5664

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

4629

6

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习