Java 8 中的谓词

Predicates in Java 8

我有一个程序可以分析文本的某些属性。代码的基本结构对于所有属性都是相同的,它仅在一行中有所不同:webDataField.containsAttributeXYZ(); 如下所示:

for (int index = 0; index < fields.size(); index++) {
    WebDataField webDataField = fields.get(index);
    boolean expectedCondition = webDataField.containsAttributeXYZ(); // Varies at this line..

    Double score = evaluateBooleanCondition(actualCondition, expectedCondition);

    WebDataFields fieldName = webDataField.getFieldName();
    ...
}

我不想为每个条件编写相同的代码(并在代码中重复自己),而是想一次编写代码的主体并将条件(计算结果为 true 或 false)传递给方法。

我是 Java Predicate 的新手,但如果我理解正确的话,这正是 Java.

中谓词的功能

这是否迫使我在自己的 class 中编写每个条件,然后让 class 实现 Predicate 接口?

如果是这样,该函数(之前在包含类似函数的 class 中声明)将需要转换为如下形式:

class ContainsAttributeXYZ implements Predicate<Boolean>

这会导致代码变得混乱并引发程序中 classes 数量的大量增加(因为每个函数都需要转换为 class)

或者我对谓词在 Java 中的工作方式有什么误解?还有其他方法吗?

谢谢

这是一个以 Predicate 作为参数的示例方法:

void processFields(List<WebDataField> fields, Predicate<WebDataField> predicate) {
    for (WebDataField webDataField : fields) {
        boolean expectedCondition = predicate.test(webDataField);
    }
}

您可以通过传递方法引用来调用它,如下所示:

processFields(fields, WebDataField::containsAttributeXYZ);
processFields(fields, WebDataField::containsAttributeABC);

其中containsAttributeXYZcontainsAttributeABCWebDataFieldclass即returnboolean的方法。或者您可以在不修改 WebDataField 的情况下创建内联 lambda。例如。 :

processFields(fields, w -> w.getFieldName().length() > 5);

您不需要创建实现 Predicate

的 class

您无需创建新的 class 即可创建 Predicate。这是因为 Java 8 添加了 lambda 语法,您可以将其视为 shorthand 用于匿名内部 classes 实现仅具有一种方法的接口。这是一个例子:

Predicate<Boolean> containsXYZ = b -> {
    return !b;
};

这相当于:

Predicate<Boolean> containsXYZ = new Predicate<Boolean>() {
    public boolean test(Boolean b) {
        return !b;
    }
};

如果您的谓词只是 returns 单个表达式的结果,它可以缩短为:

Predicate<Boolean> containsXYZ = b -> !b;

或者,函数可以是对方法的引用:

Predicate<Boolean> containsXYZ = MyClass::myMethod; // for static methods, or
Predicate<Boolean> containsXYZ = this::myMethod; // for instance methods

这是一个单行谓词,如果输入为假,则 returns 为真,反之亦然。现在,对于您的用例,您可能需要这样的东西:

static void checkAttributes(Predicate<WebDataField> containsAttributeXYZ) {
    for (WebDataField webDataField : fields) {
        boolean expectedCondition = containsAttributeXYZ.test(webDataField);
        Double score = evaluateBooleanCondition(actualCondition, expectedCondition);
        WebDataFields fieldName = webDataField.getFieldName();

        ...
    }
}

要详细了解 lambda 的工作原理,请阅读 Java Tutorial