JDK中Predicate接口源码解析和使用详解

Posted 秋9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK中Predicate接口源码解析和使用详解相关的知识,希望对你有一定的参考价值。

目录

1.Predicate接口简介

2.Predicate接口源码阅读

3.Predicate接口各方法使用举例

4.Predicate接口工作运用


1.Predicate接口简介

Predicate接口表示一个参数的谓词,是一个布尔值函数。

  1. JDK8 新增的函数式接口,提供一个抽象方法test, 接受一个参数, 根据这个参数进行一些判断, 返回判断结果 true / false
  2. 提供4个默认的default方法, 即and, or, negate,isEqual 用于进行组合判断
  3. 在流stream中被广泛使用

2.Predicate接口源码阅读

JDK中Predicate接口源码,位置在jdk的src.zip文件中的java.util.function.Predicate.java文件,

详细如下。

package java.util.function;

import java.util.Objects;

/**
 * Represents a predicate (boolean-valued function) of one argument.
 * 表示一个参数的谓词(布尔值函数)
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
* 接收一个参数, 判断这个参数是否匹配某种规则, 匹配成功返回true, 匹配失败则返回false
     */
    boolean test(T t);

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code false}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
	 * default方法, 接收另外一个Predicate<T>类型参数进行逻辑与操作
	 * 返回一个新的Predicate
	 * Predicate<T> newPredicate = (t) -> this.test(t) && other.test(t);
     * 如果传入的Predicate为空, 会抛出空指针异常
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
	 * default方法, 返回当前Predicate取反操作之后的Predicate
	 * Predicate<T> newPredicate = (t) -> !test(t);
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code true}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
	 * default方法, 接收另外一个Predicate<T>类型参数进行逻辑或操作
	 * 返回一个新的Predicate
	 * Predicate<T> newPredicate = (t) -> this.test(t) || other.test(t);
     * 如果传入的Predicate为空, 会抛出空指针异常
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     * 接收一个Object targetRef, 返回一个Predicate<T>类型
     * 返回的Predicate的test方法是用来判断传入的参数是否等于targetRef
     * 如Predicate<T> predicate = Predicate.isEqual("demo");
     * 等同于Predicate<T> predicate = t -> "demo".equals(t);
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

3.Predicate接口各方法使用举例

public class PredicateTest {
    // 辅助打印方法
    private static void print(Object obj) {
        System.out.println(obj);
    }

    public static void main(String[] args) {
        String demeStr="中国";
        Predicate<String> predicate = item -> demeStr.equals(item);
        // 1. test 方法测试
        print("1---> " + predicate.test(demeStr));
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

        // 2. Predicate 返回一个List中的偶数
        // list.stream(), 表示将List作为流进行处理, filter()方法接收一个Predicate, toArray是将流转换成数组
        Object[] result = list.stream().filter(t -> t % 2 == 0).toArray();
        print("2---> " + Arrays.toString(result));

        // 3. 测试Predicate的and方法, 打印list中大于3, 小于6的数字
        Predicate<Integer> predicate1 = t -> t > 3;
        predicate1 = predicate1.and(t -> t < 6);
        result = list.stream().filter(predicate1).toArray();
        print("3---> " + Arrays.toString(result));

        // 4. 测试Predicate的or方法, 打印list中小于3或大于5的数字
        predicate1 = t -> t < 3;
        predicate1 = predicate1.or(t -> t > 5);
        result = list.stream().filter(predicate1).toArray();
        print("4---> " + Arrays.toString(result));

        // 5. 测试Predicate的negate方法, 返回list中大于等于3,小于等于5的数字, 即对场景4取反
        result = list.stream().filter(predicate1.negate()).toArray();
        print("5---> " + Arrays.toString(result));

        // 6. 测试静态方法isEqual方法, 个人感觉这个方法没啥用处
        predicate = Predicate.isEqual(demeStr);
        print("6---> " + predicate.test(demeStr));
        print("6---> " + predicate.test(demeStr+"1"));
    }

}

运行结果如下:

 

4.Predicate接口工作运用

    /**
     * 所有的数: 1, 2, 3, 4, 5, 6, 7, 8, 9,
     * 奇数: 1, 3, 5, 7, 9,
     * 大于6的数: 7, 8, 9,
     */
    public static void main(String args[]){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        System.out.print("所有的数: ");
        eval(list, n -> true);
        System.out.print("\\n奇数: ");
        eval(list, n-> n%2 == 1 );
        System.out.print("\\n大于6的数: ");
        eval(list, n -> n > 6 );
    }

    private static void eval(List<Integer> list, Predicate<Integer> predicate) {
        list.stream().filter( n -> predicate.test(n)).forEach(e -> System.out.print(e+","));
    }

运行结果为:

 

以上是关于JDK中Predicate接口源码解析和使用详解的主要内容,如果未能解决你的问题,请参考以下文章

JDK中Funtion接口源码解析和使用详解

JDK中Funtion接口源码解析和使用详解

jdk8-Predicate相关函数式接口

Java—Java 8 新增特性详解(Predicate和Stream)

JDK8日常开发系列:Consumer详解

JDK8日常开发系列:Consumer详解