Streams:使用方法引用时“无法将Comparator转换为int”

时间:2017-08-15 20:12:10

标签: java-8 java-stream

假设我有一个字符串流:

Stream<String> stream = Stream.of("c","a","b");

这样可行:

stream.sorted(Comparator.reverseOrder())

但是使用替代语法不会:

stream.sorted(Comparator::reverseOrder)
                        ^
   Bad return type in method reference: cannot convert Comparator<T> to int

当我在我的IDE中按Ctrl +左键单击时,我都会转到同一个静态方法,在Comparator类中返回一个Comparator:

  public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

一本书解释说:

  

比较器是一个功能界面。这意味着我们可以使用   方法引用或lambda来实现它。比较器接口   实现一个方法,它接受两个String参数并返回一个   int。但是,Comparator :: reverseOrder不会这样做。它是一个   引用一个接受零参数并返回a的函数   比较器。这与界面不兼容。这意味着   我们必须使用方法而不是方法参考。

但我不明白。

4 个答案:

答案 0 :(得分:2)

简而言之,您需要一个Comparator而不是对返回一个方法的引用。方法引用适用于任何与Comparator签名匹配的方法。

的实际替代方案
stream.sorted(Comparator.reverseOrder())

stream.sorted((o1, o2) -> Comparator.<String>reverseOrder().compare(o1, o2));

由于sorted方法接受Comparator<? super T>个实例,Comparator::reverseOrder无法在此使用,因为它是Supplier<Comparator<String>>的实例。< / p>

答案 1 :(得分:2)

方法引用等同于只能在需要FunctionalInterface的情况下使用的Lambda表达式。 sorted并不期望FunctionalInterface,它需要简单的Comparator。如果sorted的签名如下,则方法参考将起作用:<T> sorted(Supplier<? extends Comparator<T>> s)

答案 2 :(得分:1)

如果功能接口中的方法具有类型参数,则不能将lambda表达式用于功能接口。

参考这个答案 - https://stackoverflow.com/a/22588738/8202194

要验证,请尝试此操作 -

class MyComparator implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        return o1.compareTo(o2);
    }
}

MyComparator myComparator = new MyComparator();
stream.sorted(myComparator::compare).forEach(s ->System.out.println(s));

这是有效的,因为compare的{​​{1}}方法在这种情况下知道类型 - MyComparator

答案 3 :(得分:0)

当比较器在java中工作时,它会比较两个值并返回-1表示较小,0表示相等,1表示较大。方法引用返回类型Comparator,但Collections逆序方法需要一个int来知道被比较的元素是小还是大,以便它可以排序。

例如,它比较一个数组[c,a,b,c] 首先它将c与a进行比较(默认情况下它使用自然顺序进行比较),因此它将返回1,这意味着c大于a。 当它比较a到b时,它将返回-1,这意味着a小于b

使用这些返回值是比较器如何使用接口中提供的默认.sort()进行排序