Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining Java 8 lambda predicates with logical operators

I have a Stream<SomeClass> stream whereas SomeClass has boolean methods isFoo() and isBar().

I'd like to check that all elements in the stream have both isFoo() and isBar() equals to true. I can check this conditions individually via SomeClass:isFoo and SomeClass::isBar lambdas.

But how would I combine these two lambdas with a logical operator like and/&&?

One obvious way is to write an extra lambda:

stream.allMatch(item -> item.isFoo() && item.isBar());

But I'd like to avoid writing an extra lambda.

Another way is to cast to Predicate<? super SomeClass>:

stream.allMatch(((Predicate<? super SomeClass>) SomeClass::isFoo).and(SomeClass::isBar));

Is there a better way - without casts and explicit lambdas?

like image 577
lexicore Avatar asked Jan 10 '17 15:01

lexicore


2 Answers

If there were a hypothetical Predicate.of method, you could write:

stream.allMatch(Predicate.of(SomeClass::isFoo).or(SomeClass::isBar));

It doesn't exist, but you could write it yourself.

public final class Predicates {
    public static <T> Predicate<T> of(Predicate<T> predicate) {
        return predicate;
    }
}

That said, I would personally go with your first option.

stream.allMatch(item -> item.isFoo() && item.isBar());

:: method references are nice but sometimes you have to write explicit lambdas.

like image 99
John Kugelman Avatar answered Oct 29 '22 20:10

John Kugelman


This might not qualify as the answer (please don't up vote it if it does not), but I sort of had the same need, to munch together some predicates and I just wrote a small utility for that.

private static <T> Predicate<T> andPredicates(Predicate<T>... predicates) {
    return Arrays.stream(predicates).reduce(Predicate::and).orElse(x -> true);
}
like image 29
Eugene Avatar answered Oct 29 '22 21:10

Eugene