Reputation: 10662
java.util.function.Predicate
has some useful methods like and
, or
, etc. which are more concise than creating a bracket orgy with multiple logical operators. Unfortunately there seems to be no way to use these functions without actually having a Predicate explictely first...
Predicate<String> predicate = String::isEmpty;
Predicate<String> predicateWithAnd = predicate.and( MyClass::testSomething );
Is there a way to create the 2nd Predicate in only one statement (thus "saving" a variable), like...
Predicate<String> predicateWithAnd = (String::isEmpty).and( MyClass::testSomething ); // That doesn't seem to work ;-)
Just curious...
Upvotes: 3
Views: 2239
Reputation: 6966
Yes, you need to cast your lambda on Predicate type, where T is your type. Example with Person class.
Predicate<Person> a = ((Predicate<Person>)p -> p.getId() > 2)
.and(p -> p.getPrice() > 100);
Upvotes: 6
Reputation: 100329
It's not very clear why str -> str.isEmpty() && MyClass.testSomething(str)
is called as "bracket orgy". It's readable and short. In general these and
, or
methods are useful when you have ready Predicate
objects. You should not use them to combine method references or lambdas.
If you really want to use method references, there are few tricks. First, you may create your own utility class like this:
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Predicates {
@SafeVarargs
public static <T> Predicate<T> and(Predicate<T>... preds) {
return Stream.of(preds).reduce(Predicate::and).orElse(x -> true);
}
@SafeVarargs
public static <T> Predicate<T> or(Predicate<T>... preds) {
return Stream.of(preds).reduce(Predicate::or).orElse(x -> false);
}
}
And use it like this:
import static mypackage.Predicates.*;
Predicate<String> predicateWithAnd = and(String::isEmpty, MyClass::testSomething);
Alternatively you may create only one quite useless static method:
public static <T> Predicate<T> pred(Predicate<T> pred) {
return pred;
}
And use it like this:
pred(String::isEmpty).and(MyClass::testSomething);
This is much shorter than explicit type cast. However I would still recomment to stay with explicit lambda like str -> str.isEmpty() && MyClass.testSomething(str)
.
Upvotes: 5