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);
其中containsAttributeXYZ
和containsAttributeABC
是WebDataField
class即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。
我有一个程序可以分析文本的某些属性。代码的基本结构对于所有属性都是相同的,它仅在一行中有所不同: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);
其中containsAttributeXYZ
和containsAttributeABC
是WebDataField
class即returnboolean
的方法。或者您可以在不修改 WebDataField
的情况下创建内联 lambda。例如。 :
processFields(fields, w -> w.getFieldName().length() > 5);
您不需要创建实现 Predicate
您无需创建新的 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。