【问题标题】:Misunderstanding about Comparator in java 8java 8中对Comparator的误解
【发布时间】:2014-11-29 18:04:45
【问题描述】:
public class Test {
    public static void main(String[] args) {
        List<Pair<String, Integer>> list = new ArrayList<>();
        list.add(new Pair<>("1", 8));
        list.add(new Pair<>("3", 2));
        list.add(new Pair<>("2", 15));

        list.stream()
            .sorted(Comparator.comparingInt(p -> p.v))
            .map(p -> p.k)
            .forEach(System.out::println);

    }
}

class Pair<K, V> {
    K k;
    V v;
    public Pair(K k, V v) {
        this.k = k;
        this.v = v;
    }
}

好的,正如你所理解的,这段代码正在打印我的配对键,从关联的最低值到最高值,所以我得到了预期的输出:

3 1 2

到目前为止一切顺利。现在我想做相反的事情,我以为我只需要做

list.stream()
    .sorted(Comparator.comparingInt(p -> p.v).reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

但是我得到一个编译错误:

v cannot be resolved or is not a field

所以看起来comparingInt 正在返回一个Comparator&lt;Object&gt;。为什么会这样?它不应该返回Comparator&lt;Integer&gt; 吗?

这些都可以通过 Eclipse Luna 版本 1 和 javac 重现。

javac -version => 1.8.0
java  -version => java version "1.8.0_25"

哦,如果您觉得它太笼统,也可以随意更改我的问题的标题,但我找不到正确的术语

【问题讨论】:

  • 它可能适用于 Comparator.reverseOrder。
  • @assylias 那么我将如何使用 reverseOrder 来实现呢?这意味着我的 pair 对象已经具有可比性。
  • @RobertBain Exaclty 我在找什么。谢谢 =) 您可以将其作为副本关闭。

标签: java java-8 comparator


【解决方案1】:

我相信只是类型推断失败了,基本上 - 因为 reverse() 调用妨碍了 sorted() 的预期参数类型和 lambda 表达式。

如果你明确指定comparingInt的类型,你可以这样做:

list.stream()
    .sorted(Comparator.<Pair<String, Integer>>comparingInt(p -> p.v).reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

或者如果你只是先声明比较器:

Comparator<Pair<String, Integer>> forward = Comparator.comparingInt(p -> p.v);
list.stream()
    .sorted(forward.reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

我觉得应该有一个Stream.reverseSorted,所以让这种事情变得非常容易,但它看起来并不存在:(

【讨论】:

  • ... 这很丑,那我更喜欢使用sorted((p1, p2) -&gt; p2.v.compareTo(p1.v))。那么这可能是编译器中的一个错误?
  • @user2336315:我同意这很丑 - 但这并不意味着它是编译器中的错误。我相信这是语言中类型推断的限制,这不是一回事。老实说,我从来没有完全理解 Java 中的泛型类型推断是如何工作的(我相信随着时间的推移它在一些地方发生了变化)——但这对我来说绝对是一个简单的限制。
  • @user2336315:我很高兴罗伯特的回答与我的相似:)
  • 不是编译器中的错误。类型推断永远不会完美;它有内在的局限性,我们越用力地推动它,超过它的极限时的效果就越令人惊讶。也就是说,我还要指出,您可以使用显式类型的 lambda 获得相同的效果,它比泛型方法调用中的显式类型见证人稍微不那么笨重。
  • 另见stackoverflow.com/a/26883991/2711488 换句话说,虽然类型推断对于方法链接失败,但它确实适用于嵌套方法调用。因此,您可以使用 Collections.reverseOrder(Comparator.comparingInt(p -&gt; p.v)) 而不是 Comparator.comparingInt(p -&gt; p.v).reversed(),这样就可以了……
猜你喜欢
  • 2017-06-26
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多