Java中的谓词

sri*_*nth 100 java predicate guava

我正在浏览PredicateJava 中使用的代码.我从来没用过Predicate.有人可以指导我Predicate在Java中的任何教程或概念解释及其实现吗?

pol*_*nts 203

我假设你在谈论com.google.common.base.Predicate<T>番石榴.

来自API:

确定给定输入的值truefalse值.例如,a RegexPredicate可以实现Predicate<String>,并且对于与其给定正则表达式匹配的任何字符串返回true.

这实际上是boolean测试的OOP抽象.

例如,您可能有一个这样的帮助方法:

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}
Run Code Online (Sandbox Code Playgroud)

现在,给定a List<Integer>,您只能处理这样的偶数:

    List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    for (int number : numbers) {
        if (isEven(number)) {
            process(number);
        }
    }
Run Code Online (Sandbox Code Playgroud)

随着Predicate,if测试被抽象出来作为一种类型.这允许它与API的其余部分进行互操作,例如Iterables,它具有许多实用方法Predicate.

因此,您现在可以编写如下内容:

    Predicate<Integer> isEven = new Predicate<Integer>() {
        @Override public boolean apply(Integer number) {
            return (number % 2) == 0;
        }               
    };
    Iterable<Integer> evenNumbers = Iterables.filter(numbers, isEven);

    for (int number : evenNumbers) {
        process(number);
    }
Run Code Online (Sandbox Code Playgroud)

请注意,现在for-each循环在没有if测试的情况下更简单.Iterable<Integer> evenNumbers通过filter使用a 定义,我们达到了更高的缩减水平Predicate.

API链接


关于高阶函数

Predicate允许Iterables.filter用作所谓的高阶函数.就其本身而言,这提供了许多优点.以List<Integer> numbers上面的例子为例.假设我们想测试所有数字是否为正数.我们可以这样写:

static boolean isAllPositive(Iterable<Integer> numbers) {
    for (Integer number : numbers) {
        if (number < 0) {
            return false;
        }
    }
    return true;
}

//...
if (isAllPositive(numbers)) {
    System.out.println("Yep!");
}
Run Code Online (Sandbox Code Playgroud)

使用a Predicate,并与其他库互操作,我们可以改为写:

Predicate<Integer> isPositive = new Predicate<Integer>() {
    @Override public boolean apply(Integer number) {
        return number > 0;
    }       
};

//...
if (Iterables.all(numbers, isPositive)) {
    System.out.println("Yep!");
}
Run Code Online (Sandbox Code Playgroud)

希望你现在可以看到在更高的抽象价值对于喜欢"过滤由给定的谓词的所有元素","检查是否所有元素满足给定谓词"等做出更好的代码例程.

不幸的是,Java没有一流的方法:你不能将方法传递给Iterables.filterIterables.all.当然,您可以使用Java 传递对象.因此,Predicate定义了类型,并且您传递实现此接口的对象.

也可以看看

  • 我没有提到Guava的Predicate,我应该在我的问题中清楚.但是你的解释帮助我理解了我在寻找什么,谓词逻辑在java中使用的方式.感谢您的精心解释 (4认同)

Mic*_*yan 14

谓词是一个返回真/假(即布尔)值的函数,而不是一个真/假(即布尔)值的命题.在Java中,不能有独立的函数,因此可以通过为表示谓词的对象创建接口来创建谓词,然后提供实现该接口的类.谓词的接口示例可能是:

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}
Run Code Online (Sandbox Code Playgroud)

然后你可能有一个实现,如:

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}
Run Code Online (Sandbox Code Playgroud)

为了更好地理解概念,您可能需要阅读有关一阶逻辑的内容.

编辑 Java API自Java 8开始定义了
一个标准的Predicate接口(java.util.function.Predicate).在Java 8之前,您可能会发现重用com.google.common.base.Predicate接口很方便.番石榴.

另请注意,从Java 8开始,使用lambdas编写谓词要简单得多.例如,在Java 8及更高版本中,可以传递p -> true给函数,而不是像上面那样定义一个命名的Tautology子类.