I'm trying to create a finder which takes several predicates and reduces them:
public static <T extends BusinessInterface> Collection<T> findOr(
Context pContext, Class<T> pClass, Predicate<? super T>... pPredicates) {
Predicate<? super T> lReducedPredicate =
Arrays.asList(pPredicates).stream().reduce(Predicate::or).orElse(r -> false);
return find(pContext, pClass, lReducedPredicate);
}
Unfortunately I get following compiler error:
Predicate lReducedPredicate = Arrays.asList(pPredicates).stream().reduce(Predicate::or).orElse(r -> false);
incompatible types: Predicate cannot be converted to Predicate
where T is a type-variable:
T extends BusinessInterface declared in method findOr(Context,Class,Predicate...)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object super: T from capture of ? super T
CAP#2 extends Object super: T from capture of ? super T
I get not errors in Eclipse and I have no idea what is going wrong.
Any help is really appreciated :).
One way to solve this is using
public static <T extends BusinessInterface> Collection<T> findOr(
Context pContext, Class<T> pClass, Predicate<? super T>... pPredicates) {
Predicate<? super T> lReducedPredicate = Arrays.asList(pPredicates).stream()
.reduce((a,b) -> t -> a.test(t) || b.test(t)).orElse(r -> false);
return find(pContext, pClass, lReducedPredicate);
}
While you can’t invoke the or
method on a Predicate<? super T>
instance with another Predicate<? super T>
as argument, you can create the same function, or
would return, yourself, as passing a T
instance to either test
method is valid.
Your code works for me in intellij, but not in ideone, which is strange.
The reason for the compiler error is that you're effectively trying to do this:
Predicate<? super T> a = null;
Predicate<? super T> b = null;
a.or(b); // Compiler error!
Because of the separate wildcards on both a
and b
, the compiler can't guarantee that the type bounds are compatible, because those wildcards are not necessarily the same.
Anyway, try this one weird trick:
Arrays.asList(pPredicates)
.stream()
.map(a -> a) // Here!
.reduce(Predicate::or)
.orElse(r -> false);
Inserting this line allows it to cast to the type which matches the type constraints.