Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Predicate with and/or/negate methods in one statement?

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...

like image 458
Florian Schaetz Avatar asked Dec 05 '25 10:12

Florian Schaetz


2 Answers

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);
like image 96
ByeBye Avatar answered Dec 07 '25 22:12

ByeBye


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).

like image 22
Tagir Valeev Avatar answered Dec 08 '25 00:12

Tagir Valeev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!