Java Stream流中的filter()使用方法举例详解
作者:昕er
前言
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()
不仅可以用于简单类型的流(如 Integer
、String
),也可以用于复杂对象的流。例如,在一个包含 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()使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!