java 8 中Predicate接口的学习

29 篇文章 0 订阅

参考资料:https://www.cnblogs.com/rever/p/9773743.html

今天来学习下 Predicate 断定接口,Predicate是个断言式接口其参数是<T,boolean>,也就是给一个参数T,返回boolean类型的结果。Predicate的具体实现是根据传入的lambda表达式来决定的。

来看源码:

@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}
     */
    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> 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<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> 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)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

通过源码可以看到,Predicate默认的方法是test(T t),三个重要的方法 and or negate,对应java中的 && || !。

简单的上一个代码演示下:

    @Test
    public void first(){
        List<Integer> list=new ArrayList<>();
        for(int i = 1; i < 20; i++){
            list.add(i);
        }
        Predicate<Integer> p1 = i -> i > 5;
        Predicate<Integer> p2 = i -> i<20;
        Predicate<Integer> p3 = i -> i%2 == 0;
        // 大于5
        List lt = list.stream().filter(p1).collect(Collectors.toList());
        System.out.println(lt);
        // 小于20
        lt = list.stream().filter(p2).collect(Collectors.toList());
        System.out.println(lt);
        // 偶数
        lt = list.stream().filter(p3).collect(Collectors.toList());
        System.out.println(lt);
        // 大于5并且小于20的偶数
        lt = list.stream().filter(p1.and(p2).and(p3)).collect(Collectors.toList());
        System.out.println(lt.toString());
    }

}

我们定义了三个断言p1,p2,p3。现在有一个从1~20的list,我们需要过滤这个list。上述的filter是先单个条件过滤打印,最后一个是组合条件过滤出所有大于5小于20,并且是偶数的列表结果显示如下:

[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

[2, 4, 6, 8, 10, 12, 14, 16, 18]

[6, 8, 10, 12, 14, 16, 18]

假如突然我们的需求变了,我们现在需要过滤出奇数。那么我不可能直接去改Predicate,因为实际项目中这个条件可能在别的地方也要使用。那么此时我只需要更改filter中Predicate的条件。

// 大于5并且小于20的奇数
lt = list.stream().filter(p1.and(p2).and(p3.negate())).collect(Collectors.toList());
System.out.println(lt.toString());

结果:

[7, 9, 11, 13, 15, 17, 19]

我们直接对p3这个条件取反就可以实现了。是不是很简单?

isEqual这个方法是static类型,返回类型是Predicate,所以我们也可以把它作为函数式接口进行使用。我们可以当做==操作符来使用。

// 大于5等于10
lt = list.stream().filter(p1.and(Predicate.isEqual(10))).collect(Collectors.toList());
System.out.println(lt);

结果:

[10]

Predicate接口还有几个基本类型的扩展,IntPredicate、LongPredicate,收入相应的int long参数,返回类似都是boolean,用法也相同,只是这两个接口都没有static类型的isEqual方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值