转自https://segmentfault.com/a/1190000012256677

Predicate函数式接口的主要作用就是提供一个test方法,接受一个参数返回一个布尔类型,Predicate在stream api中进行一些判断的时候非常常用。

@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);
}

使用泛型T指定传入的参数类型,我们通过一个根据不同条件取出不同数据的例子来看下Predicate具体应用

public class PredicateTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(, , , , , , , , , );
PredicateTest predicateTest = new PredicateTest();
//输出大于5的数字
List<Integer> result = predicateTest.conditionFilter(list, integer -> integer > );
result.forEach(System.out::println);
System.out.println("-------");
//输出大于等于5的数字
result = predicateTest.conditionFilter(list, integer -> integer >= );
result.forEach(System.out::println);
System.out.println("-------");
//输出小于8的数字
result = predicateTest.conditionFilter(list, integer -> integer < );
result.forEach(System.out::println);
System.out.println("-------");
//输出所有数字
result = predicateTest.conditionFilter(list, integer -> true);
result.forEach(System.out::println);
System.out.println("-------");
}
//高度抽象的方法定义,复用性高
public List<Integer> conditionFilter(List<Integer> list, Predicate<Integer> predicate){
return list.stream().filter(predicate).collect(Collectors.toList());
}
}

我们只定义了一个conditionFilter方法,stream()会将当前list作为源创建一个Stream对象,collect(Collectors.toList())是将最终的结果封装在ArrayList中(这部分会在后续stream学习中详细介绍,这里只关注filter即可),filter方法接收一个Predicate类型参数用于对目标集合进行过滤。里面并没有任何具体的逻辑,提供了一种更高层次的抽象化,我们可以把要处理的数据和具体的逻辑通过参数传递给conditionFilter即可。理解了这种设计思想后,再看上面的例子就很容易理解,本身逻辑并不复杂,分别取出小于5、大于等于5、小于8的元素,最后一个总是返回true的条件意味着打印出集合中所有元素。
除此之外,Predicate还新增了接口的默认(default)方法和(static)静态方法。在Java 8以前,接口里的方法要求全部是抽象方法。但是静态(static)方法只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用;默认(default)方法只能通过接口实现类的对象来调用。

default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
} default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
} default Predicate<T> negate() {
return (t) -> !test(t);
} static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}

and方法接收一个Predicate类型,也就是将传入的条件和当前条件以并且的关系过滤数据。or方法同样接收一个Predicate类型,将传入的条件和当前的条件以或者的关系过滤数据。negate就是将当前条件取反。看下具体使用方式

public List<Integer> conditionFilterNegate(List<Integer> list, Predicate<Integer> predicate){
return list.stream().filter(predicate.negate()).collect(Collectors.toList());
} public List<Integer> conditionFilterAnd(List<Integer> list, Predicate<Integer> predicate,Predicate<Integer> predicate2){
return list.stream().filter(predicate.and(predicate2)).collect(Collectors.toList());
} public List<Integer> conditionFilterOr(List<Integer> list, Predicate<Integer> predicate,Predicate<Integer> predicate2){
return list.stream().filter(predicate.or(predicate2)).collect(Collectors.toList());
} //大于5并且是偶数
result = predicateTest.conditionFilterAnd(list, integer -> integer > , integer1 -> integer1 % == );
result.forEach(System.out::println);//6 8 10
System.out.println("-------"); //大于5或者是偶数
result = predicateTest.conditionFilterOr(list, integer -> integer > , integer1 -> integer1 % == );
result.forEach(System.out::println);//2 4 6 8 9 10
System.out.println("-------"); //条件取反
result = predicateTest.conditionFilterNegate(list,integer2 -> integer2 > );
result.forEach(System.out::println);// 1 2 3 4 5
System.out.println("-------");

我们分别借助Predicate的三个默认方法定义了conditionFilterAnd、conditionFilterOr和conditionFilterNegate方法。然后再下方调用这三个方法,根据传入的判断条件观察输出结果。

最后再来看一下Predicate接口中的唯一一个静态方法,Java8中接口中除了增加了默认方法也可以定义静态方法。

/**
* 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);
}

isEqual方法返回类型也是Predicate,也就是说通过isEqual方法得到的也是一个用来进行条件判断的函数式接口实例。而返回的这个函数式接口实例是通过传入的targetRef的equals方法进行判断的。我们看一下具体用法

System.out.println(Predicate.isEqual("test").test("test"));//true

这里会用第一个"test"的equals方法判断与第二个"test"是否相等,结果true。

Java8-6-Predicate接口详解的更多相关文章

  1. Atitit.jdk java8的语法特性详解 attilax 总结

    Atitit.jdk java8的语法特性详解 attilax 总结 1.1. 类型推断这个特别有趣的.鲜为人知的特性1 2. Lambda1 2.1. 内部迭代意味着改由Java类库来进行迭代,而不 ...

  2. Java8 Stream新特性详解及实战

    Java8 Stream新特性详解及实战 背景介绍 在阅读Spring Boot源代码时,发现Java 8的新特性已经被广泛使用,如果再不学习Java8的新特性并灵活应用,你可能真的要out了.为此, ...

  3. JDBC常用接口详解

    JDBC中常用接口详解 ***DriverManager 第一.注册驱动 第一种方式:DriverManager.registerDriver(new com.mysql.jdbc.Driver()) ...

  4. Java6.0中Comparable接口与Comparator接口详解

    Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...

  5. socket接口详解

    1. socket概述 socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket起源于UNIX,在Unix一切 ...

  6. “全栈2019”Java第八十四章:接口中嵌套接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. “全栈2019”Java第八十三章:内部类与接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. Java接口 详解(二)

    上一篇Java接口 详解(一)讲到了接口的基本概念.接口的使用和接口的实际应用(标准定义).我们接着来讲. 一.接口的应用—工厂设计模式(Factory) 我们先看一个范例: package com. ...

  9. [转载]MII/MDIO接口详解

    原文地址:MII/MDIO接口详解作者:心田麦浪 本文主要分析MII/RMII/SMII,以及GMII/RGMII/SGMII接口的信号定义,及相关知识,同时本文也对RJ-45接口进行了总结,分析了在 ...

  10. map接口详解

    1.Map接口详解(1)映射(map)是一个存储键.键值对的对象,给定一个键,可以查询得到它的值,键和值都可以是对象(2)键必须是唯一的,值可以重复(Map接口映射唯一的键到值)(3)有些映射可以接收 ...

随机推荐

  1. 鹅厂优文|打通小程序音视频和webRTC

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯视频云终端技术总监常青, 2008 年毕业加入腾讯,一直从事客户端研发相关工作,先后参与过 PC QQ.手机QQ.QQ物联 等产品 ...

  2. Oracle12c中性能优化&amp;功能增强新特性之临时undo

    临时表最有意思的特点之一是undo段也存储在常规undo表空间中,而它们的undo反过来被redo保护,这会导致一些问题. 1)  写undo表空间需要数据库以读写模式打开,因此,只读数据库和物理备库 ...

  3. SOFA 源码分析 — 连接管理器

    前言 RPC 框架需要维护客户端和服务端的连接,通常是一个客户端对应多个服务端,而客户端看到的是接口,并不是服务端的地址,服务端地址对于客户端来讲是透明的. 那么,如何实现这样一个 RPC 框架的网络 ...

  4. 前端应该了解的PWA

    一.传统web 应用 当前web应用在移动时代并没有达到其在桌面设备上流行的程度,下面有张图来对比与原生应用之间的差别. 究其原因,无外乎下面不可避免的几点: 移动设备网络限制-不可忽略的加载时间 w ...

  5. iframe 背景透明设置--兼容IE

    iframe标签添加: allowTransparency="true"属性. 子文件body背景设置透明: background-color: transparent;.

  6. ASP.NET(C#) Repeater分页的实现

    ASP.NET(C#) Repeater分页的实现 第一种方式: 数据库连接代码: using System; using System.Data; using System.Configuratio ...

  7. 洛谷 P3853 解题报告

    P3853 路标设置 题目背景 B市和T市之间有一条长长的高速公路,这条公路的某些地方设有路标,但是大家都感觉路标设得太少了,相邻两个路标之间往往隔着相当长的一段距离.为了便于研究这个问题,我们把公路 ...

  8. C Primer Plus 第7章 C控制语句:分支和跳转 编程练习

    作业练习 1. #include <stdio.h> int main(void) { char ch; int spare, other, n; //空格,其他字符,换行 spare = ...

  9. Spring Aop技术原理分析

    本篇文章从Aop xml元素的解析开始,分析了Aop在Spring中所使用到的技术.包括Aop各元素在容器中的表示方式.Aop自动代理的技术.代理对象的生成及Aop拦截链的调用等等.将这些技术串联起来 ...

  10. 浅谈通信网络(三)——TCP/IP协议

    简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...