我正在浏览Predicate
Java 中使用的代码。我从来没有用过Predicate
。有人可以指导我了解Predicate
Java 及其实现的任何教程或概念解释吗?
4 回答
我假设你说的是com.google.common.base.Predicate<T>
番石榴。
从 API:
确定给定输入的
true
或false
值。例如,aRegexPredicate
可能实现Predicate<String>
,并为匹配其给定正则表达式的任何字符串返回 true。
这本质上是boolean
测试的 OOP 抽象。
例如,您可能有一个这样的辅助方法:
static boolean isEven(int num) {
return (num % 2) == 0; // simple
}
现在,给定 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);
}
}
使用Predicate
,if
测试被抽象为一种类型。Iterables
这允许它与 API 的其余部分进行互操作,例如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);
}
if
请注意,现在 for-each 循环在没有测试的情况下要简单得多。我们通过使用 a定义Iterable<Integer> evenNumbers
,达到了更高层次的抽象。filter
Predicate
API 链接
Iterables.filter
- 返回满足谓词的元素。
关于高阶函数
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.filter
and Iterables.all
。当然,您可以在 Java 中传递对象。因此,Predicate
类型被定义,并且您传递实现此接口的对象。
也可以看看
谓词是返回真/假(即布尔)值的函数,与作为真/假(即布尔)值的命题相反。在 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 之前,您可能会发现重用com.google.common.base.Predicate接口很方便番石榴。
另外,请注意,从 Java 8 开始,使用 lambda 编写谓词要简单得多。例如,在 Java 8 和更高版本中,可以传递p -> true
给一个函数,而不是像上面那样定义一个命名的重言式子类。
加上迈克尔所说的:
在 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);