简体   繁体   English

Java 8中的谓词

[英]Predicates in Java 8

I have a program that analyzes text for certain attributes. 我有一个程序来分析某些属性的文本。 The basic structure of the code is the same for all attributes it only varies in one line: webDataField.containsAttributeXYZ(); 代码的基本结构对于所有属性都是相同的,它只在一行中变化: webDataField.containsAttributeXYZ(); as seen here: 如下所示:

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();
    ...
}

Instead of writing the same code for each condition (& repeating myself in code) I'd like to write the main body of the code once and pass the condition (which evaluates to true or false) to the method. 而不是为每个条件编写相同的代码(并在代码中重复自己),我想编写代码的主体一次,并将条件(计算结果为true或false)传递给方法。

I am new to Java Predicate but if I understand correctly this is exactly the function of predicates in Java. 我是Java Predicate新手,但如果我理解正确,这正是Java中谓词的功能。

Does this force me to write each condition in its own class and then have that class implement the Predicate interface? 这是否迫使我在自己的类中编写每个条件,然后让该类实现Predicate接口?

If so, the function (which is previously declared in a class that contains similar functions) will need to be converted to something like: 如果是这样,该函数(先前在包含类似函数的类中声明)将需要转换为如下所示:

class ContainsAttributeXYZ implements Predicate<Boolean>

This would cause the code to become disoriented and trigger a large increase in the number of classes in the program (as every function needs to be converted into a class) 这会导致代码迷失方向并触发程序中类的数量大量增加(因为每个函数都需要转换为类)

Or did I misunderstand something about how Predicates work in Java? 或者我误解了Predicates如何在Java中工作? Is there another way of doing this? 还有另一种方法吗?

Thanks 谢谢

Here is an example method that takes a Predicate as an argument: 这是一个以Predicate为参数的示例方法:

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

and you would call it by passing a method reference, like this: 你可以通过传递方法引用来调用它,如下所示:

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

Where containsAttributeXYZ and containsAttributeABC are methods of WebDataField class that return boolean . containsAttributeXYZcontainsAttributeABC是返回booleanWebDataField类的方法。 Or you can create a lambda inline without modifying WebDataField . 或者,您可以在不修改WebDataField情况下创建lambda内联。 Eg : 例如:

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

You don't need to create a class that implements Predicate 您不需要创建实现Predicate的类

You don't need to create a new class to create a Predicate . 您不需要创建新类来创建Predicate This is because Java 8 added a lambda syntax, which you can think of as a shorthand for anonymous inner classes implementing an interface with only one method. 这是因为Java 8添加了一个lambda语法,您可以将其视为匿名内部类的简写,仅使用一个方法实现接口。 Here is an example: 这是一个例子:

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

This is equivalent to: 这相当于:

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

If your predicate just returns the result of a single expression, it can be shortened to: 如果您的谓词只返回单个表达式的结果,则可以缩短为:

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

Alternatively, a function can be a reference to a method: 或者,函数可以是对方法的引用:

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

This is a one-line predicate that returns true if the input is false, and vice versa. 这是一个单行谓词,如果输入为false,则返回true,反之亦然。 Now, for your use case, you might want something like this: 现在,对于您的用例,您可能需要以下内容:

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

        ...
    }
}

For a thorough explanation of how lambdas work, read the Java Tutorial . 有关lambda如何工作的详细说明,请阅读Java教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM