Is it possible to chain predicates with `and` using different type parameter?

1.1k views Asked by At

I am learning Java 8 lambdas. Can I join two predicates, with different type parameter, using and method in Predicate interface?

This is my code:

Predicate<Integer> pc = (iv) -> iv > 20;
Predicate<String> pL = (is) -> is.length() > 5;
System.out.println("The predicate result for pc is: " + pc.test(25));
System.out.println("===========");
System.out.println("The predicate result with both condition true: " + pc.and(pL.test("abcd")));
1

There are 1 answers

5
Polygnome On BEST ANSWER

No, you can not chain predicates of different types, unless the chained predicate also accepts the type of the original predicate.

Looking at the signature, you can easily see that:
and(Predicate<? super T> other)
or(Predicate<? super T> other)

You can chain predicates:

Predicate<Person> isMale = p -> p.isMale();
Predicate<Person> isAdult = p -> p.age() >= AGE_OF_MATURITY;
Predicate<Person> isAdultMale = isAdult.and(isMale);

You can only chain predicates that accept at least (thats what the ? super T says) the same type as the original predicate:

Predicate<Object> hasWeirdHashCode = o -> o.hashCode() == 0;
Predicate<Person> nonsense = isMale.and(hasWeirdHashCode);

If you want to test different types (A, B), you need to provide them separately:

Predicate<A> propertyOfA = [...];
Predicate<B> propertyOfB = [...];

BiPredicate<A,B> propertyOfAnB = (a, b) -> 
    propertyOfA.test(a) && propertyOfB.test(b);

If you need more than two different types, you need to roll your own, custom TriPredicate, QuadPredicate and so on functional interfaces, which should be straight-forward to implement.