Alferd Nobel
Alferd Nobel

Reputation: 3979

chained java.util.function.Predicate call to compare predicates

I'm trying to get this working :

Predicate<Integer> predicateInteger = i ->  i>0;
System.out.println(predicateInteger.test(1)); // works and prints true

Now I'm trying to define another predicate like on predicateInteger using equals :

// stmt below DOES NOT COMPILE : Target type of a lambda conversion must be an interface

Predicate<Integer> predicateEq = predicateInteger.equals(i -> new Boolean(true));
System.out.println(predicateEq.test(8));// I want this to print "TRUE" on equals .

What am I doing wrong here ?

Upvotes: 2

Views: 1633

Answers (2)

Alferd Nobel
Alferd Nobel

Reputation: 3979

This helped me achieve what I want :

// when this is the first predicate:
Predicate<Integer> predicateInteger = i ->  i>0;  
// and when this second predicate compares with the first, 
Predicate<Integer> predicateEq = predicateInteger.and(i -> i<6); 
// then :
System.out.println(predicateEq.test(5));// prints true

Upvotes: 0

Nikolas
Nikolas

Reputation: 44476

This is not how predicates and functional interfaces (lambda expressions) in general. The Predicate class has the only method boolean test(T t). The lambda expression is nothing different from an anonymous class implementation. Notice there is no equals method, therefore the lambda expressions are not comparable (in terms of equality).

Predicate<Integer> predicateInteger = i -> i > 0;
Predicate<Integer> predicateInteger = new Predicate<Integer>() {
    @Override
    public boolean test(Integer i) {
        return i > 0;
    }
}

Actually, the Predicate#test returns boolean which can be directly printed out:

Predicate<Integer> integerPredicate = i -> i > 0;
System.out.println(integerPredicate.test(8));                                  // true

Seems you want to compare the result value to something else, defined with another Predicate.

Predicate<Integer> integerPredicate = i -> i > 0;
Predicate<Object> resultPredicate = i -> true;

boolean result = integerPredicate.test(8) == resultPredicate.test("whatever");
System.out.println(result);                                                    // true

Note that, in fact, Predicate<Object> predicate = i -> true is practically a Supplier which returns a constant value regardless the input (actually, it has no input).

Predicate<Integer> integerPredicate = i -> i > 0;
Supplier<Boolean> resultSupplier = () -> true;

boolean result = integerPredicate.test(8) == resultSupplier.get();
System.out.println(result);                                                    // true

However, this makes no sense as long as the integerPredicate can be printed out directly with no resultSupplier.

Predicate<Integer> integerPredicate = i -> i > 0;
System.out.println(integerPredicate.test(8));                                  // true

... and we are back at the beginning.


The last thing that comes to my mind is to print out the result always on the method test call. All you need is to define a decorator, that wraps the Predicate delegate and submits an action on the test method call using Consumer<Boolean where Boolean is the former predicate's result.

@AllArgsConstructor // constructor omitted (Lombok) for sake of brevity
public class CallbackPredicate<T> implements Predicate<T> {

    private final Predicate<T> delegate;
    private final Consumer<Boolean> callback;

    @Override
    public final boolean test(final T t) {
        boolean result = delegate.test(t);
        callback.accept(result);
        return result;
    }
}
Predicate<Integer> integerPredicate = new CallbackPredicate<>(
        i -> i > 0,                                              // Predicate<Integer>
        System.out::println);                                    // Callback

integerPredicate.test(8);                                        // prints true

The predicates can be also chained using the AND clause represented by the Predicate#and method:

Predicate<Integer> largerThanZero = i -> i > 0;
Predicate<Integer> smallerThanSix = i -> i < 6;

Predicate<Integer> betweenZeroAndSix = largerThanZero.and(smallerThanSix);

System.out.println(betweenZeroAndSix.test(-5));                  // false
System.out.println(betweenZeroAndSix.test(5));                   // true
System.out.println(betweenZeroAndSix.test(15));                  // false

Upvotes: 3

Related Questions