一、源码学习
Predicate 是 Java 8 中的一个函数式接口。它的源码定义如下:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
该接口定义了一个抽象方法 test,表示一个参数的布尔判断。同时,该接口还提供了 and、negate、or 和 isEqual
等多个默认方法。其中,and 方法用于将两个 Predicate 对象的判断结果通过逻辑与操作合并,返回一个新的 Predicate 对象;negate
方法用于将当前 Predicate 对象的判断结果取反,返回一个新的 Predicate 对象;or 方法用于将两个 Predicate
对象的判断结果通过逻辑或操作合并,返回一个新的 Predicate 对象;isEqual 方法是一个静态方法,用于判断两个对象是否相等。该接口还使用了注解 @FunctionalInterface,表示该接口只包含一个抽象方法,可以被当做函数式接口使用。
需要注意的是,该接口的实现一般通过 Lambda 表达式或方法引用来实现,例如:
Predicate<Integer> isPositive = num -> num > 0;
上述代码中,我们使用 Lambda 表达式来实现 Predicate 接口的 test 方法,从而定义了一个名为 isPositive 的
Predicate 接口的实现。该实现判断一个整数是否为正数,如果是则返回 true,否则返回 false。
二、基础入门
Predicate 是 Java 8
中的一个函数式接口,它接受一个参数并返回一个布尔值,适用于需要对特定类型的对象进行逻辑判断的场景。下面我们来介绍如何使用 Predicate
接口。
- 基本语法
Predicate 接口定义了一个抽象方法 test,该方法接受一个参数并返回一个布尔值。通常,我们会使用 Lambda 表达式来实现
Predicate 接口的抽象方法。例如,我们可以使用如下方式定义一个 Predicate 接口的实现:
Predicate<Integer> isPositive = num -> num > 0;
上述代码中,我们定义了一个名为 isPositive 的 Predicate 接口的实现,该实现用于判断一个数是否为正数。
下面是一个简单的示例,展示了如何使用 Predicate 接口来筛选一个整数列表中的正数:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(-2, -1, 0, 1, 2);
Predicate<Integer> isPositive = num -> num > 0;
List<Integer> positiveNumbers = numbers.stream()
.filter(isPositive)
.collect(Collectors.toList());
System.out.println("Positive numbers: " + positiveNumbers);
// 输出: Positive numbers: [1, 2]
}
}
输出结果为:
Positive numbers: [1, 2]
可以看到,我们成功使用 Predicate 接口实现了对整数列表的筛选。
- 复合使用
Predicate 接口中提供了多个默认方法,可以实现复合表达式,即将多个 Predicate 接口的实现进行组合。
- and 方法实现与操作,将两个 Predicate 接口的实现组合成新的 Predicate 实现,要求两个 Predicate 实现均返回 true。
例如,我们可以使用如下代码将两个 Predicate 实现组合成一个新的实现:
Predicate<Integer> isGreaterThanZero = num -> num > 0;
Predicate<Integer> isEven = num -> num % 2 == 0;
Predicate<Integer> greaterThanZeroAndEven = isGreaterThanZero.and(isEven);
上述代码中,我们将两个 Predicate 实现 isGreaterThanZero 和 isEven 组合成一个新的实现
greaterThanZeroAndEven,该实现会对输入的数值进行判断,要求其大于 0
且为偶数,只有同时满足这两个条件时,新的实现才会返回 true。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(-2, -1, 0, 1, 2);
Predicate<Integer> isGreaterThanZero = num -> num > 0;
Predicate<Integer> isEven = num -> num % 2 == 0;
Predicate<Integer> greaterThanZeroAndEven = isGreaterThanZero.and(isEven);
List<Integer> positiveEvenNumbers = numbers.stream()
.filter(greaterThanZeroAndEven)
.collect(Collectors.toList());
System.out.println("Positive even numbers: " + positiveEvenNumbers);
// 输出: Positive even numbers: [2]
}
}
输出结果为:
Positive even numbers: [2]
- or 方法实现或操作,将两个 Predicate 接口的实现组合成新的 Predicate 实现,要求两个 Predicate 实现中至少有一个返回 true。
例如,我们可以使用如下代码将两个 Predicate 实现组合成一个新的实现:
Predicate<Integer> isGreaterThanZero = num -> num > 0;
Predicate<Integer> isLessThanZero = num -> num < 0;
Predicate<Integer> greaterOrLessThanZero = isGreaterThanZero.or(isLessThanZero);
上述代码中,我们将两个 Predicate 实现 isGreaterThanZero 和 isLessThanZero 组合成一个新的实现
greaterOrLessThanZero,该实现会对输入的数值进行判断,要求其大于 0 或小于
0,只要满足其中任意一个条件,新的实现就会返回 true。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(-2, -1, 0, 1, 2);
Predicate<Integer> isGreaterThanZero = num -> num > 0;
Predicate<Integer> isLessThanZero = num -> num < 0;
Predicate<Integer> greaterOrLessThanZero = isGreaterThanZero.or(isLessThanZero);
List<Integer> positiveOrNegativeNumbers = numbers.stream()
.filter(greaterOrLessThanZero)
.collect(Collectors.toList());
System.out.println("Positive or negative numbers: " + positiveOrNegativeNumbers);
// 输出: Positive or negative numbers: [-2, -1, 1, 2]
}
}
输出结果为:
Positive or negative numbers: [-2, -1, 1, 2]
- negate 方法实现取反操作,将一个 Predicate 接口的实现取反。
例如,我们可以使用如下代码将一个 Predicate 实现取反:
Predicate<Integer> isNotGreaterThanZero = isGreaterThanZero.negate();
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(-2, -1, 0, 1, 2);
Predicate<Integer> isGreaterThanZero = num -> num > 0;
Predicate<Integer> isNotGreaterThanZero = isGreaterThanZero.negate();
List<Integer> notPositiveNumbers = numbers.stream()
.filter(isNotGreaterThanZero)
.collect(Collectors.toList());
System.out.println("Not positive numbers: " + notPositiveNumbers);
// 输出: Not positive numbers: [-2, -1, 0]
}
}
输出结果为:
Not positive numbers: [-2, -1, 0]
上述代码中,我们将一个 Predicate 实现 isGreaterThanZero 取反,得到一个新的实现
isNotGreaterThanZero,该实现会对输入的数值进行判断,要求其不大于 0,如果输入的数值小于等于 0,则新的实现返回
true。
- 示例代码
下面是一个使用 Predicate 接口的示例代码,它将使用 Lambda 表达式实现一个 Predicate
接口的实现,用于判断一个字符串是否是空字符串:
public class PredicateExample {
public static void main(String[] args) {
Predicate<String> isEmpty = str -> str == null || str.isEmpty();
System.out.println(isEmpty.test(null)); // 输出 true
System.out.println(isEmpty.test("")); // 输出 true
System.out.println(isEmpty.test("hello")); // 输出 false
}
}
在上述代码中,我们定义了一个名为 isEmpty 的 Predicate
接口的实现,该实现用于判断传入的字符串是否为空字符串,如果为空字符串则返回 true,否则返回
false。然后我们使用该实现对不同的字符串进行判断,并打印出判断的结果。
Predicate 接口是 Java 8
中的一个函数式接口,它接受一个参数并返回一个布尔值,适用于需要对特定类型的对象进行逻辑判断的场景。下面将介绍 Predicate
接口的使用场景以及具体使用案例。
三、使用场景
1、筛选符合条件的元素
例如,从一个列表中筛选出符合特定条件的元素:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
在上面的代码中,我们使用 Predicate 接口的实现来判断一个数是否为偶数,然后使用 filter 方法将偶数过滤出来,最终使用
collect 方法将过滤结果转换为一个列表。
2、校验参数
使用 Predicate 可轻松实现对传入参数的校验:
void validate(Predicate<String> validationRule, String str) {
if (validationRule.test(str)) {
System.out.println("Validation passed");
} else {
System.out.println("Validation failed");
}
}
Predicate<String> rule = s -> s.startsWith("A");
validate(rule, "Apple"); // 输出Validation passed
validate(rule, "Banana"); // 输出Validation failed
在上面的代码中,我们定义了一个 validate 方法,该方法接受一个 Predicate 作为规则,然后使用 test
方法对传入的字符串进行校验。
具体使用案例:
假设我们有一个 Student 类,它包含 name、age 和 score 三个属性,我们想要使用 Predicate
接口来对学生进行筛选。
代码如下:
@Data
public class Student {
private String name;
private int age;
private int score;
}
public class PredicateExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Tom", 18, 80),
new Student("Jerry", 21, 90),
new Student("John", 19, 85),
new Student("Mary", 20, 88)
);
// 筛选出年龄大于等于20且分数在80到90之间的学生
Predicate<Student> agePredicate = student -> student.getAge() >= 20;
Predicate<Student> scorePredicate = student -> student.getScore() >= 80 && student.getScore() <= 90;
List<Student> result = students.stream()
.filter(agePredicate.and(scorePredicate))
.collect(Collectors.toList());
System.out.println(result);
}
}
在上面的代码中,我们定义了一个 Student 类和一个 PredicateExample 类。在 PredicateExample
类中,我们首先定义了一个包含四个 Student 对象的列表。然后,我们使用两个 Predicate
实现分别对年龄和分数进行判断,筛选出符合条件的学生,最后将结果转换为一个列表。
总结:
Predicate 接口适用于需要对特定类型的对象进行逻辑判断的场景。它可以用于筛选符合条件的元素,也可以用于校验传入参数的合法性。使用
Predicate 接口可以更加简洁、易读和易懂地实现这些功能。