逐步走向响应式编程-常见函数式接口- Predicate<T>

Posted 浦江之猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逐步走向响应式编程-常见函数式接口- Predicate<T>相关的知识,希望对你有一定的参考价值。

在了解函数式接口前,希望大家有一定的lamda表达式的基础,可以参考此博客。本文细说一下java8常见的函数式接口-Predicate,希望对大家有一定的帮助。

本接口用的比较多,称之为断言接口,用于条件判断,其中唯一需要实现的方法为test(T t),其实现逻辑通常作为一个参数传到某个方法中。本人觉得可以这样去理解 Predicate,其实例是一个条件,条件是用来判断test(T t)中的参数是否成立,所以最终的关系是“条件.test(t)”。

源码解析

package java.util.function;
import java.util.Objects;
/**
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is @link #test(Object).
 *函数式接口,需要唯一实现的方法是test
 * @param <T> the type of the input to the predicate
 * java8引入的
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> 
    /**
     *对给定的参数判断其是否符合条件,所以实现test方法就是实现一套判断逻辑
     * @param t the input argument
     * @return @code true if the input argument matches the predicate,
     * otherwise @code false
     */
    boolean test(T t);
    /**
     * 与操作,可以用&&代替
     *
     * @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> and(Predicate<? super T> other) 
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    
    /**
     *对给定的条件进行取反操作
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() 
        return (t) -> !test(t);
    
    /**
     * 或操作,可以用||代替
     * @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> or(Predicate<? super T> other) 
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    
    /**
     *判断对象是否相关
     * @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)
     */
    static <T> Predicate<T> isEqual(Object targetRef) 
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    
    /**
     *java11 引进的一个静态方法,用于取反,对negate方法进行了封装
     * @param <T>     the type of arguments to the specified predicate
     * @param target  predicate to negate
     *
     * @return a predicate that negates the results of the supplied
     *         predicate
     *
     * @throws NullPointerException if target is null
     *
     * @since 11
     */
    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) 
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    

案例分析

test方法

//判断一个数大于0
//因为此接口中只有一个待实现的接口,所以这里基本都会用lamda表达式来编写判断逻辑
Predicate<Integer> predicate = t -> t > 0;
System.out.println(predicate.test(2));

如果需要经常使用的话,一般会封装成方法。

public boolean test(int i, Predicate<Integer> predicate) 
        predicate.test(i);

//使用
对象.test(2,i->i>0);

and 方法

需要传入Predicate

//判断一个数大于3,且能被4整除
 Predicate<Integer> predicate = i->i>3;
 predicate.and(i->i%4==0).test(5);

一般情况如果判断条件少的话我直接会用&&来代替and

//判断一个数大于3,且能被4整除
 Predicate<Integer> predicate = i->i>3 && i%4==0;
 predicate.test(5);

or 方法

需要传入Predicate

//判断能被2整除,或者能被4整除
 Predicate<Integer> predicate = i->i%2==0;
 predicate.and(i->i%4==0).test(8);

同and 一样,如果如果判断条件少的话我直接会用||来代替or

//判断能被2整除,或者能被4整除
 Predicate<Integer> predicate = i->i%2==0 ||i->i%4==0;
 predicate.test(8);

negate方法

相当于取非操作,这个方法跟andor 不同,它不需要传入Predicate,也是唯一一个不需要传入参数的函数。

//判断一个数不大于2
 Predicate<Integer> predicate = i->i>2;
 predicate.negate().test(8);

not方法

java11 提供的一个静态方法,也是取非操作,对negate进行了封装,需要传入Predicate.

//判断一个数不大于2
//这里需要注意的时,参数上要加上类型转换
Predicate.not(i->(Integer)i>2).test(3);

isEqual方法

此方法是一个静态方法,返回值为Predicate,需要传入一个对象,与test中的参数进行比较。

//判断两个字符串是否相等
Predicate.isEqual("str1").test("str2");

万能方法

本人在工作中通常只写一个方法来处理大部分的判断,这样就不用每次都声明一个Predicate 变量。在函数外将构造好的条件与待判断的对象传入即可。

//万能判断
public static <T> void multiFunction(T t, Predicate<T> predicate) 
        if (predicate.test(t)) 
            System.out.println(t);
        
    
//判断一个字符串长度是否大于2
类名. multiFunction("s1", t -> t.length()>2);

//判断一个数能否被2整除
类名.multiFunction(3, t -> t%2==0);
//判断两个字符串是否相等
 multiFunction("str1", Predicate.isEqual("str2"));

总结

内容很简单,所有的判断都会汇聚到test上,因为test是唯一需要实现的接口,也就是说所有的判断逻辑都是在test中实现的。在java8的Stream中,Predicate使用很广泛,后续的博文中会一一介绍。最后希望本文能帮助大家,祝大家在IT之路上少走弯路,一路绿灯不堵车,测试一性通过,bug秒解!

以上是关于逐步走向响应式编程-常见函数式接口- Predicate<T>的主要内容,如果未能解决你的问题,请参考以下文章

逐步走向响应式编程-常见函数式接口- Function<T, R>

逐步走向响应式编程-常见函数式接口- Function<T, R>

逐步走向响应式编程-常见函数式接口- Consumer<T>

逐步走向响应式编程-常见函数式接口- Consumer<T>

iOS 中的链式编程函数式编程入门

函数响应式编程和 RxSwift+MVVM