糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > predicate java 作用_Java函数式编程接口详解之Predicate

predicate java 作用_Java函数式编程接口详解之Predicate

时间:2021-09-30 10:10:28

相关推荐

predicate java 作用_Java函数式编程接口详解之Predicate

一、初识

Predicate是Java提供的重要的函数编程接口之一,作用主要是用于逻辑判断。

首先看看源码:

@FunctionalInterface

public interface Predicate {

boolean test(T t);

default Predicate and(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) && other.test(t);

}

default Predicate negate() {

return (t) -> !test(t);

}

default Predicate or(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) || other.test(t);

}

static Predicate isEqual(Object targetRef) {

return (null == targetRef)

? Objects::isNull

: object -> targetRef.equals(object);

}

}

对函数式编程接口有一定了解的同学可能会疑惑,为啥 有这么多方法,不是说函数式编程接口只有一个方法吗?确实没错,但这个方法只限于没有实现的方法,不包括有实现的方法,自从Java引入了default关键字后,在接口内是可以编写default方法的。

喏,上面不是还有一个static方法?其实想想也是能想得通的,static方法属于类的信息,不属于实例信息,我们平时编码的时候可能不会这么写,但是不代表不可以这么写哦。

二、基础用法

我们现在不必纠结其他方法,把注意力集中在boolean test(T t)方法上。我们先看一段示例代码:

List list = Arrays.asList(1, 2, 3, 4, 6);

List list1 = list.stream()

.filter(num -> num < 5)

.collect(Collectors.toList());

这段代码就是过滤列表中小样5的数字,并生成一个新的列表,当我们点进filter方法的实现,代码如下:

@Override

public final Stream filter(Predicate super P_OUT> predicate) {

Objects.requireNonNull(predicate);

return new StatelessOp(this, StreamShape.REFERENCE,

StreamOpFlag.NOT_SIZED) {

@Override

Sink opWrapSink(int flags, Sink sink) {

return new Sink.ChainedReference(sink) {

@Override

public void begin(long size) {

downstream.begin(-1);

}

@Override

public void accept(P_OUT u) {

if (predicate.test(u))

downstream.accept(u);

}

};

}

};

}

这里我们暂时不要关心其他代码,注意点放在两个地方,一个就是filter的参数列表filter(Predicate super P_OUT> predicate),另一个就是predicate.test(u)。

看到这个两个地方,你或许就明白了我们平时常用的filter方法其实就是依赖Predicate函数接口来完成逻辑判断的。

那我们该如何使用Predicate接口呢?请看用例:

// 逻辑判断工具

public class LogicUtil {

public static boolean qualified(Predicate predicate, Person person) {

return predicate.test(person);

}

}

// 测试代码

public static void main(String[] args) {

List list = Arrays.asList(new Person("小明",180), new Person("小刚", 178));

for (Person person : list) {

if (LogicUtil.qualified(p -> p.getHeight() >= 180, person)) {

System.out.println(person.getName() + "身高合格!");

}

}

}

这里只是举了一很简单的例子,过滤身高大于180的。这里我们将过滤的条件由调用者传入,能够增加编程的灵活性,也就是说逻辑的判断由调用者自行实现。

Predicate使用场景推荐:

在一个公共函数内,大部分逻辑是通用的,但是一小部分判断逻辑是不一样的,可以使用Predicate作为公共函数的入参,将那一小部分判断逻辑通过Lambda表达式的方式传入公共函数。就像上面filter函数的实现一样。

三、高阶用法

既然是接口,那么我们当然可以去实现它啦。如果你的判断逻辑比较复杂,用Lambda表达式比较繁琐或不够整洁时,你可以去实现Predicate接口,如下:

// 实现接口

public class Filter implements Predicate {

@Override

public boolean test(Person person) {

return person.getHeight() >= 180 && Objects.equals(person.getGender(), "man");

}

}

// 工具

public class LogicUtil {

public static boolean qualified3(Predicate filter, Person person) {

return filter.test(person);

}

}

// 测试代码

public static void main(String[] args) {

List list = Arrays.asList(new Person("小明",180, "man"),

new Person("小刚", 178, "man"),

new Person("小红", 190, "woman"));

for (Person person : list) {

if (LogicUtil.qualified3(new Filter(), person)) {

System.out.println(person.getName() + "合格!");

}

}

}

这种用法在抽象设计方面有很大的优势。

四、Predicate的其他方法

文章开头我们就看到Predicate接口内还有and、negate、or、isEqual等方法,下面就简单的介绍一下。

4.1 and

先看看and函数的源码:

default Predicate and(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) && other.test(t);

}

说明:在返回语句中,(t)是lambda表达式的参数,test(t) && other.test(t)是主体。

and函数的功能就是拼接两个Predicate,返回新的Predicate,看看用法:

// 身高过滤器

public class HeightFilter implements Predicate {

@Override

public boolean test(Person person) {

return person.getHeight() >= 180;

}

}

// 性别过滤器

public class GenderFilter implements Predicate {

@Override

public boolean test(Person person) {

return Objects.equals(person.getGender(), "man");

}

}

// 测试代码

public static void main(String[] args) {

List list = Arrays.asList(new Person("小明", 180, "man"),

new Person("小刚", 178, "man"),

new Person("小红", 190, "woman"));

List list1 = list.stream()

.filter(new HeightFilter().and(new GenderFilter()))

.collect(Collectors.toList());

}

4.2 negate

先看看negate函数源码:

default Predicate negate() {

return (t) -> !test(t);

}

函数很简单,就是返回predicate的否定。

用法:

// 身高过滤器

public class HeightFilter implements Predicate {

@Override

public boolean test(Person person) {

return person.getHeight() >= 180;

}

}

// 测试代码

public static void main(String[] args) {

List list = Arrays.asList(new Person("小明", 180, "man"),

new Person("小刚", 178, "man"),

new Person("小红", 190, "woman"));

List list1 = list.stream()

.filter(new HeightFilter().negate())

.collect(Collectors.toList());

}

就是返回所有身高小于180的数据人。

4.3 or

default Predicate or(Predicate super T> other) {

Objects.requireNonNull(other);

return (t) -> test(t) || other.test(t);

}

学完and函数,理解or就没啥问题了,简单说,就是满足众多条件中一个一个即可:

// 身高过滤器

public class HeightFilter implements Predicate {

@Override

public boolean test(Person person) {

return person.getHeight() >= 180;

}

}

// 性别过滤器

public class GenderFilter implements Predicate {

@Override

public boolean test(Person person) {

return Objects.equals(person.getGender(), "woman");

}

}

// 测试代码

public static void main(String[] args) {

List list = Arrays.asList(new Person("小明", 180, "man"),

new Person("小刚", 178, "man"),

new Person("小红", 160, "woman"));

List list1 = list.stream()

.filter(new HeightFilter().or(new GenderFilter()))

.collect(Collectors.toList());

}

此时,小明、小红都满足条件

4.4 isEqual

再来看看最后一个静态方法:

static Predicate isEqual(Object targetRef) {

return (null == targetRef)

? Objects::isNull

: object -> targetRef.equals(object);

}

咋一看,有的小伙伴可能不是很理解,其实拆分一下也不难。

首先很容易看出里面是一个三目运算符;

其次Objects::isNull就是lambda表达式的一种简化写法,还原就是如下语句:

object -> Objects.isNull(object)

即:当targetRef=null时,Objects.isNull(object)的结果就是Predicate的结果

否则,返回object -> targetRef.equals(object)

用法:

// 测试代码

public static void main(String[] args) {

Person xiaoming = new Person("小明", 180, "man");

List list = Arrays.asList(xiaoming,

new Person("小刚", 178, "man"),

new Person("小红", 160, "woman"));

List list1 = list.stream()

.filter(Predicate.isEqual(xiaoming))

.collect(Collectors.toList());

}

五、Predicate的其他变体

接口名

参数

返回类型

描述

BiPredicate

(T, U)

boolean

接受两个参数

DoublePredicate

double

boolean

接受double类型参数

IntPredicate

int

boolean

接受int类型参数

LongPredicate

long

boolean

接受long类型参数

好了,有关Predicate接口的介绍到此为止,(づ ̄3 ̄)づ╭❤~

如果觉得《predicate java 作用_Java函数式编程接口详解之Predicate》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。