Predicate函数式接口-在stream流中的使用

一、源码学习

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
接口。

  1. 基本语法

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 接口实现了对整数列表的筛选。

  1. 复合使用

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。

  1. 示例代码

下面是一个使用 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 接口可以更加简洁、易读和易懂地实现这些功能。

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Stream 是 Java 8 提供的一个用于处理集合数据的函数式编程 API。Stream API 可以让我们以一种声明式的方式处理集合数据,避免了传统的迭代方式,使代码更加简洁和易读。 而流(Stream)是一个来自数据源的元素队列并支持聚合操作。元素是特定类型的对象,形成一个队列。流操作可以执行顺序或并行。Java 中的 Stream API 可以使得我们可以使用一种类似于 SQL 语句在集合中执行流操作。 Stream API 的主要特点如下: - Stream 不存储数据,它们只是在源的基础上提供了一种视图。 - Stream 操作是延迟执行的,只有当终止操作调用时才会执行。 - Stream 可以操作集合、数组等数据源。 - Stream 提供了丰富的中间操作和终止操作,可以实现过滤、映射、排序、聚合等功能。 函数式接口(Functional Interface)是 Java 8 中引入的一个概念,它是只包含一个抽象方法的接口。Stream API 使用函数式接口作为其操作的参数,例如 filter、map、reduce 等方法都接受函数式接口作为参数,以便进行相应的操作。 在 Stream API 中,常用的函数式接口Predicate、Function、Consumer、Supplier 等,它们可以通过 Lambda 表达式或方法引用来创建,并可以与流操作相结合使用,实现各种数据处理操作。 希望这个回答能够解决你对 Stream函数式接口的疑问。如果还有其他问题,请随时提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值