Overview
在本篇短文中,我们将学习如何在 Java 11 中优雅地对一个 Predicate 方法引用进行取反操作。
我们会先回顾在 Java 11 之前我们是如何处理这类问题的,以及当时的局限性。然后,我们会介绍 Java 11 引入的 Predicate.not()
方法,并通过实际代码演示其用法。
Java 11 之前的做法
在 Java 11 之前,如果我们想对一个 Predicate
进行取反,通常只能使用 lambda 表达式显式写出取反逻辑。
举个例子,我们先定义一个 Person
类,包含 age
字段和 isAdult()
方法:
public class Person {
private static final int ADULT_AGE = 18;
private int age;
public Person(int age) {
this.age = age;
}
public boolean isAdult() {
return age >= ADULT_AGE;
}
}
假设我们有如下人员列表:
List<Person> people = Arrays.asList(
new Person(1),
new Person(18),
new Person(2)
);
如果我们想筛选出成年人,Java 8 中可以这样写:
people.stream()
.filter(Person::isAdult)
.collect(Collectors.toList());
✅ 使用 Person::isAdult
方法引用,代码简洁清晰。
❌ 但如果我们想筛选出非成年人,Java 8 中只能这样写:
people.stream()
.filter(person -> !person.isAdult())
.collect(Collectors.toList());
这时候就不能使用方法引用了,必须写成 lambda 表达式,牺牲了代码的简洁性。
一种变通方式是添加 isNotAdult()
方法:
public boolean isNotAdult() {
return !isAdult();
}
然后这样使用:
people.stream()
.filter(Person::isNotAdult)
.collect(Collectors.toList());
⚠️ 但有时候我们不希望暴露这个方法到 API 中,或者我们根本无法修改原始类(比如它来自第三方库),这就显得有些笨拙了。
Java 11 中的 Predicate.not() 方法
Java 11 引入了 Predicate.not()
方法,允许我们对一个 Predicate 进行取反,同时保持方法引用的可读性。
继续使用上面的例子,我们现在可以这样写:
people.stream()
.filter(Predicate.not(Person::isAdult))
.collect(Collectors.toList());
✅ 这样既保留了方法引用的语义清晰,又实现了逻辑取反。
我们还可以通过静态导入进一步简化代码:
import static java.util.function.Predicate.not;
// ...
people.stream()
.filter(not(Person::isAdult))
.collect(Collectors.toList());
⚠️ 注意:使用静态导入时要注意命名冲突,避免影响代码可读性。
总结
- Java 11 引入的
Predicate.not()
方法让我们可以在不使用 lambda 表达式的情况下对谓词进行取反。 - 它保留了方法引用带来的可读性和简洁性。
- 适用于需要对已有
Predicate
方法进行取反操作,但又不想修改类结构或牺牲代码风格的场景。
完整代码示例可参考:GitHub 项目地址