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();
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.
I am new to Java Predicate
but if I understand correctly this is exactly the function of predicates in Java.
Does this force me to write each condition in its own class and then have that class implement the Predicate
interface?
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? Is there another way of doing this?
Thanks
Here is an example method that takes a Predicate
as an argument:
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
. Or you can create a lambda inline without modifying WebDataField
. E.g. :
processFields(fields, w -> w.getFieldName().length() > 5);
You don't need to create a class that implements Predicate
You don't need to create a new class to create a 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. 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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With