流减少不兼容的类型

时间:2017-07-05 08:00:30

标签: java java-8 java-stream reduce

我试图创建一个包含多个谓词并减少它们的查找程序:

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);
}

不幸的是我遇到了以下编译错误:

  

Predicate lReducedPredicate = Arrays.asList(pPredicates).stream()。reduce(Predicate :: or).orElse(r - &gt; false);   不兼容的类型:谓词无法转换为谓词   其中T是一个类型变量:   T扩展了方法findOr(Context,Class,Predicate ...)中声明的BusinessInterface   其中CAP#1,CAP#2是新的类型变量:   CAP#1扩展了Object super:T from capture?超级T   CAP#2扩展了Object super:T从捕获?超级T

我在Eclipse中没有错误,我不知道出了什么问题。

非常感谢任何帮助:)。

2 个答案:

答案 0 :(得分:7)

解决此问题的一种方法是使用

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);
}

虽然您无法使用另一个or作为参数调用Predicate<? super T>实例上的Predicate<? super T>方法,但您可以创建相同的函数,or将自己返回,将T实例传递给test方法是有效的。

答案 1 :(得分:6)

你的代码在intellij中适用于我,但不适用于ideone,这很奇怪。

编译错误的原因是您有效地尝试执行此操作:

Predicate<? super T> a = null;
Predicate<? super T> b = null;
a.or(b);  // Compiler error!

由于ab上都有单独的通配符,编译器无法保证类型边界是兼容的,因为这些通配符不一定相同。

无论如何,试试这个奇怪的伎俩:

Arrays.asList(pPredicates)
    .stream()
    .map(a -> a)  // Here!
    .reduce(Predicate::or)
    .orElse(r -> false);

插入此行允许它转换为与类型约束匹配的类型。