Java中的谓词

时间:2010-06-02 04:36:07

标签: java guava predicate

我正在浏览在Java中使用Predicate的代码。我从未使用Predicate。有人可以指导我对Predicate的任何教程或概念性解释及其在Java中的实现吗?

4 个答案:

答案 0 :(得分:201)

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

来自API:

  

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

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

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

static boolean isEven(int num) {
   return (num % 2) == 0; // simple
}

现在,给定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);
        }
    }

使用Predicateif测试被抽象为一种类型。这允许它与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);
    }

请注意,现在for-each循环在没有if测试的情况下更简单。我们通过Iterable<Integer> evenNumbers使用filter来定义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!");
}

使用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!");
}

希望您现在可以看到更高抽象的值,例如“按给定谓词过滤所有元素”,“检查所有元素是否满足给定谓词”等等,以获得更好的代码。

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

另见

答案 1 :(得分:14)

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

public interface Predicate<ARGTYPE>
{
    public boolean evaluate(ARGTYPE arg);
}

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

public class Tautology<E> implements Predicate<E>
{
     public boolean evaluate(E arg){
         return true;
     }
}

为了更好地理解概念,您可能想要了解一阶逻辑。

修改
从Java 8开始,Java API中定义了一个标准的Predicate接口(java.util.function.Predicate)。在Java 8之前,您可能会发现从{{3}重用com.google.common.base.Predicate接口很方便。 }}

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

答案 2 :(得分:0)

您可以查看java doc示例或谓词here的使用示例

基本上,它用于根据您可能具有的任何特定条件筛选结果集中的行,并对符合条件的行返回true:

 // the age column to be between 7 and 10
    AgeFilter filter = new AgeFilter(7, 10, 3);

    // set the filter.
    resultset.beforeFirst();
    resultset.setFilter(filter);

答案 3 :(得分:0)

加上Micheal所说的内容:

您可以在java中过滤集合中使用Predicate,如下所示:

public static <T> Collection<T> filter(final Collection<T> target,
   final Predicate<T> predicate) {
  final Collection<T> result = new ArrayList<T>();
  for (final T element : target) {
   if (predicate.apply(element)) {
    result.add(element);
   }
  }
  return result;
}

一个可能的谓词可以是:

final Predicate<DisplayFieldDto> filterCriteria = 
                    new Predicate<DisplayFieldDto>() {
   public boolean apply(final DisplayFieldDto displayFieldDto) {
    return displayFieldDto.isDisplay();
   }
  };

用法:

 final List<DisplayFieldDto> filteredList=
 (List<DisplayFieldDto>)filter(displayFieldsList, filterCriteria);