问题
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 :).
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/44920292/stream-reduction-incompatible-types