3

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

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
  • Please, consider [this](http://stackoverflow.com/a/28605829/2711488) and [that](http://stackoverflow.com/a/24396579/2711488) – Holger Mar 14 '16 at 10:25

2 Answers2

6

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);
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
ByeBye
  • 6,650
  • 5
  • 30
  • 63
  • Thanks. Tried that but must have made some typo then. With the explicit cast it's unfortunately not as short as I had hoped, but that's the price, I guess. – Florian Schaetz Mar 12 '16 at 12:33
4

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

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • No, that example would not be a bracket orgy, but combine some more statements with brackets, &&, || and !, then itc an happen quite quickly. – Florian Schaetz Mar 12 '16 at 12:50
  • 2
    @FlorianSchaetz, the same will happen if you combine them with the series of `and`, `or`, `negate`. You will also need multiple parentheses. – Tagir Valeev Mar 12 '16 at 13:25