问题
我正在浏览Java中使用Predicate
的代码。我从未使用过Predicate
。有人可以指导我对Predicate
的任何教程或概念性解释及其在Java中的实现吗?
#1 热门回答(200 赞)
我假设你正在谈论来自番石榴的com.google.common.base.Predicate<T>
。
来自API:
确定给定输入的true或false值。例如,RegexPredicate可能实现Predicate <String>,并且对于与其给定正则表达式匹配的任何字符串都返回true。
这实际上是aboolean
test的OOP抽象。
例如,你可能有一个这样的帮助方法:
static boolean isEven(int num) {
return (num % 2) == 0; // simple
}
现在,给定aList<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);
}
}
随着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);
}
请注意,现在for-each循环更简单,没有if
test。通过使用aPredicate
定义Iterable<Integer> evenNumbers
,filter
,我们达到了更高的缩减水平。
API链接
- Iterables.filter返回满足谓词的元素。
###在高阶函数上
Predicate
允许Iterables.filter
用作所谓的高阶函数。就其本身而言,这提供了许多优点。以上面的4333452066示例为例。假设我们想测试所有数字是否为正数。我们可以这样写:
static boolean isAllPositive(Iterable<Integer> numbers) {
for (Integer number : numbers) {
if (number < 0) {
return false;
}
}
return true;
}
//...
if (isAllPositive(numbers)) {
System.out.println("Yep!");
}
使用aPredicate
,并与其他库互操作,我们可以写这个:
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.filter
和Iterables.all
。当然,你可以在Java中传递对象。因此,定义了Predicate
type,并且你通过了对该接口的实现。
也可以看看
- 维基百科/高阶函数
- 维基百科/过滤器(高阶函数)
#2 热门回答(13 赞)
谓词是返回真/假(即布尔)值的函数,而不是作为真/假(即布尔)值的命题。在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之前,你可能会发现从Guava重用com.google.common.base.Predicate接口很方便。
另请注意,从Java 8开始,使用lambdas编写谓词要简单得多。例如,在Java 8及更高版本中,可以将p -> true
传递给函数,而不是像上面那样定义命名的Tautology子类。
#3 热门回答(0 赞)
你可以查看java doc示例或Predicatehere的使用示例
基本上,它用于根据你可能具有的任何特定条件筛选结果集中的行,并对符合条件的行返回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);