阿杰,我给你整理一份 Java Stream 的 filter 方法详解,从概念、语法、使用示例到进阶技巧。


一、filter 方法概念

  • filterJava 8 Stream API 的中间操作(Intermediate Operation)。
  • 作用:根据给定的条件(Predicate 函数式接口)过滤流中的元素,只保留满足条件的元素。
  • 特点
    1. 不改变原始集合
    2. 惰性求值(Lazy Evaluation):只有在终止操作(如 collectforEach)触发时才执行
    3. 支持链式调用

二、语法

Stream<T> filter(Predicate<? super T> predicate)

  • 参数
    • Predicate<? super T>:一个返回 boolean 的函数式接口,用来判断元素是否保留
  • 返回值
    • 返回一个 新的 Stream,包含所有满足条件的元素

三、基础示例

import java.util.*;
import java.util.stream.*;

public class FilterExample {
    public static void main(String[] args) {
        List&lt;Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        // 保留偶数
        List&lt;Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());

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

说明

  • n -> n % 2 == 0 是一个 Predicate
  • filter 返回一个 Stream
  • collect(Collectors.toList()) 是终止操作,触发 filter 执行

四、结合其他 Stream 操作

1. 链式调用

List&lt;String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

List&lt;String> filteredNames = names.stream()
                                  .filter(name -> name.length() > 3)
                                  .map(String::toUpperCase)
                                  .collect(Collectors.toList());

System.out.println(filteredNames); // 输出: [ALICE, CHARLIE, DAVID]

2. 去重 + 过滤

List&lt;Integer> nums = Arrays.asList(1,2,2,3,3,4,5);
List&lt;Integer> uniqueEven = nums.stream()
                               .distinct()
                               .filter(n -> n % 2 == 0)
                               .collect(Collectors.toList());

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


五、过滤对象属性

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

List&lt;User> users = Arrays.asList(
    new User("Alice", 20),
    new User("Bob", 17),
    new User("Charlie", 25)
);

List&lt;User> adults = users.stream()
                         .filter(u -> u.age >= 18)
                         .collect(Collectors.toList());

adults.forEach(u -> System.out.println(u.name)); // 输出: Alice, Charlie


六、进阶技巧

  1. 组合多个 Predicate
Predicate&lt;Integer> greaterThan3 = n -> n > 3;
Predicate&lt;Integer> lessThan6 = n -> n &lt; 6;

List&lt;Integer> result = numbers.stream()
                              .filter(greaterThan3.and(lessThan6))
                              .collect(Collectors.toList());
System.out.println(result); // 输出: [4, 5]

  1. 异步或并行流
List&lt;Integer> nums = Arrays.asList(1,2,3,4,5,6);
List&lt;Integer> evens = nums.parallelStream()
                          .filter(n -> n % 2 == 0)
                          .collect(Collectors.toList());

  1. 避免空指针
List&lt;String> names = Arrays.asList("Alice", null, "Bob");
List&lt;String> nonNullNames = names.stream()
                                 .filter(Objects::nonNull)
                                 .collect(Collectors.toList());


七、总结

  • filter 核心作用:过滤流中元素,保留满足 Predicate 条件的元素
  • 中间操作:惰性求值,可链式调用
  • 常见配合
    • map():转换
    • distinct():去重
    • sorted():排序
    • collect() / forEach():终止操作
  • 注意
    • filter 返回 Stream,不会修改原始集合
    • Predicate 函数要简洁,避免复杂副作用