Java Stream流中的filter()使用方法举例详解

 更新时间:2024年11月01日 10:12:14   作者:昕er  
filter()是Java Stream API中的中间操作,用于根据给定的Predicate条件筛选流中的元素,它通过接收一个返回boolean值的函数(断言)作为参数,筛选出满足条件的元素并收集到新的流中,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

filter() 是 Java Stream API 中的一个中间操作,用于根据给定的条件筛选流中的元素。它接收一个 Predicate(断言,即返回 boolean 的函数)作为参数,筛选出满足条件的元素,并将它们收集到一个新的流中。

1. 基本用法

filter() 允许你基于某些条件筛选流中的元素。例如,如果你有一个整数流,并且只想保留其中的偶数,可以使用 filter() 来实现:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)  // 保留偶数
    .collect(Collectors.toList());  // 终端操作,将结果收集为 List

System.out.println(evenNumbers);  // 输出: [2, 4, 6]

在这个例子中:

  • filter(n -> n % 2 == 0):是一个筛选条件,用于保留那些能被 2 整除的数字,即偶数。
  • filter() 会遍历流中的每个元素,使用该条件进行检查,满足条件的元素会继续留在流中,不满足条件的元素会被丢弃。

2. Predicate 函数

filter() 的参数是一个 Predicate 接口,这个接口只有一个抽象方法 boolean test(T t),它接收一个输入并返回一个 boolean 值。这个 Predicate 用来定义筛选条件。

示例:筛选大于 3 的数字

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

List<Integer> greaterThanThree = numbers.stream()
    .filter(n -> n > 3)  // 保留大于 3 的数字
    .collect(Collectors.toList());

System.out.println(greaterThanThree);  // 输出: [4, 5]

在这个例子中,n -> n > 3 是一个 Predicate,它表示筛选出大于 3 的数字。filter() 方法根据这个 Predicate 来保留满足条件的元素。

3. 链式调用 filter()

你可以多次调用 filter(),来对流中的元素应用多个条件。比如:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> filteredNumbers = numbers.stream()
    .filter(n -> n > 3)    // 第一个条件: 大于 3
    .filter(n -> n < 8)    // 第二个条件: 小于 8
    .collect(Collectors.toList());

System.out.println(filteredNumbers);  // 输出: [4, 5, 6, 7]

这里,filter() 被调用了两次:

  • 第一个 filter(n -> n > 3):筛选出大于 3 的数字。
  • 第二个 filter(n -> n < 8):在剩余的数字中筛选出小于 8 的数字。

最终结果就是同时满足这两个条件的元素 [4, 5, 6, 7]

4. 空流

filter() 操作之后,流可能会变成空流。如果没有任何元素满足 filter() 的条件,流会变成空流,但不会抛出异常。这种情况下,后续的中间操作仍然可以应用在空流上,只是没有元素可以处理:

List<Integer> numbers = Arrays.asList(1, 2, 3);

List<Integer> result = numbers.stream()
    .filter(n -> n > 10)  // 没有元素满足条件
    .collect(Collectors.toList());

System.out.println(result);  // 输出: []

在这个例子中,filter(n -> n > 10) 筛选出大于 10 的元素,但流中没有元素满足这个条件,所以最终返回的是一个空列表 []

5. filter() 的惰性求值

filter() 是一种惰性操作,也就是 中间操作。它本身并不会立即执行,而是等到流上的终端操作(如 collect()forEach())被调用时才会执行。

例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4)
    .filter(n -> {
        System.out.println("Filtering: " + n);
        return n % 2 == 0;
    });

System.out.println("Before terminal operation");

// 终端操作,触发 filter 执行
List<Integer> evenNumbers = stream.collect(Collectors.toList());

System.out.println("After terminal operation: " + evenNumbers);

输出结果为:

Before terminal operation
Filtering: 1
Filtering: 2
Filtering: 3
Filtering: 4
After terminal operation: [2, 4]

可以看到,在调用终端操作 collect() 之前,filter() 并没有执行;只有当终端操作被调用时,filter() 才真正开始过滤元素。

6. 结合其他流操作使用

filter() 常常与其他流操作结合使用,比如 map()sorted() 等。

示例:filter() 和 map() 结合使用

List<String> words = Arrays.asList("apple", "banana", "cherry", "date");

List<String> result = words.stream()
    .filter(word -> word.length() > 5)  // 筛选长度大于 5 的单词
    .map(String::toUpperCase)           // 将符合条件的单词转换为大写
    .collect(Collectors.toList());

System.out.println(result);  // 输出: [BANANA, CHERRY]

在这个例子中:

  • filter(word -> word.length() > 5):筛选出长度大于 5 的单词。
  • map(String::toUpperCase):将剩下的单词转换为大写。
  • collect(Collectors.toList()):将流结果收集为一个 List

7. 组合多个 Predicate 条件

有时候你可能需要对流中的元素应用多个条件。你可以通过 Predicate 的 and()or()negate() 等方法组合多个条件。

示例:筛选出大于 2 且是偶数的数字

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> result = numbers.stream()
    .filter(n -> n > 2 && n % 2 == 0)  // 组合条件: 大于 2 且为偶数
    .collect(Collectors.toList());

System.out.println(result);  // 输出: [4, 6]

你也可以使用 Predicate 的组合方法:

Predicate<Integer> greaterThanTwo = n -> n > 2;
Predicate<Integer> isEven = n -> n % 2 == 0;

List<Integer> result = numbers.stream()
    .filter(greaterThanTwo.and(isEven))  // 使用 Predicate 的 and() 方法
    .collect(Collectors.toList());

System.out.println(result);  // 输出: [4, 6]

这种方式能够增强代码的可读性和重用性。

8. 在对象集合中使用 filter()

filter() 不仅可以用于简单类型的流(如 IntegerString),也可以用于复杂对象的流。例如,在一个包含 Person 对象的列表中筛选年龄大于 18 的人:

class Person {
    String name;
    int age;

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

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

List<Person> people = Arrays.asList(
    new Person("Alice", 22),
    new Person("Bob", 17),
    new Person("Charlie", 20)
);

List<Person> adults = people.stream()
    .filter(person -> person.age > 18)  // 筛选年龄大于 18 的人
    .collect(Collectors.toList());

System.out.println(adults);  // 输出: [Alice (22), Charlie (20)]

总结:

  • filter() 是一个中间操作,用于根据给定的 Predicate 对流中的元素进行筛选,保留符合条件的元素。
  • 它不会改变元素的类型,只会决定哪些元素可以继续传递到下一个流操作。
  • 由于 filter() 是惰性求值的,中间操作只有在终端操作被调用时才会执行。
  • filter() 适合用于各种复杂对象的筛选,并且可以与 map() 等其他流操作结合使用。

到此这篇关于Java Stream流中的filter()使用方法的文章就介绍到这了,更多相关Java Stream流中filter()使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用IDEA如何将本地代码上传到GitCode

    使用IDEA如何将本地代码上传到GitCode

    文章主要介绍了使用GitCode进行代码仓库管理的步骤,包括注册、创建仓库、IDEA创建本地仓库、设置远程仓库、配置账号密码和进行代码推送等操作,文章强调使用CSDN账号同步注册,并使用个人访问令牌进行操作,最后完成代码的推送
    2026-04-04
  • Mybatis常见注解有哪些(总结)

    Mybatis常见注解有哪些(总结)

    这篇文章主要介绍了Mybatis常见注解有哪些(总结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Spring-cloud Config Server的3种配置方式

    Spring-cloud Config Server的3种配置方式

    这篇文章主要介绍了Spring-cloud Config Server的3种配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • idea中如何去掉不想commit的文件

    idea中如何去掉不想commit的文件

    这篇文章主要介绍了idea中如何去掉不想commit的文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java中executeQuery()和executeUpdate()的区别及说明

    Java中executeQuery()和executeUpdate()的区别及说明

    executeQuery()和executeUpdate()是JDBC中用于执行SQL语句的方法,前者用于执行查询语句,返回ResultSet对象;后者用于执行修改操作,返回受影响的行数,使用这些方法时需要注意SQL语句的正确性、资源的释放以及防止SQL注入
    2025-11-11
  • 一文深入理解Java中的深拷贝机制

    一文深入理解Java中的深拷贝机制

    在Java编程中,我们经常需要处理对象的复制问题,深拷贝和浅拷贝是两种常见的复制方式,它们在内存管理和对象引用方面存在不同特点,本文将带大家深入探究Java中的深拷贝机制,需要的朋友可以参考下
    2023-09-09
  • Java之Arrays的各种功能和用法总结

    Java之Arrays的各种功能和用法总结

    数组在 Java 中是一种常用的数据结构,用于存储和操作大量数据。Arrays 是我们在处理数组时的一把利器。它提供了丰富的方法和功能,使得数组操作变得更加简单、高效和可靠。接下来我们一起看看 Arrays 的各种功能和用法,,需要的朋友可以参考下
    2023-05-05
  • 重新认识Java中的ThreadLocal

    重新认识Java中的ThreadLocal

    ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题
    2021-05-05
  • Java编程Webservice指定超时时间代码详解

    Java编程Webservice指定超时时间代码详解

    这篇文章主要介绍了Java编程Webservice指定超时时间代码详解,简单介绍了webservice,然后分享了通过使用JDK对Webservice的支持进行Webservice调用实现指定超时时间完整示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-11-11
  • spring使用Filter过滤器对Response返回值进行修改的方法

    spring使用Filter过滤器对Response返回值进行修改的方法

    这篇文章主要介绍了spring使用Filter过滤器对Response返回值进行修改,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09

最新评论