当前位置: 首页 > 知识库问答 >
问题:

方法链接如何在Java8比较器中工作?[复制]

荆树
2023-03-14

我正在为Java8证书做准备,下面的内容让我有点困惑,也许有人能帮我?在这个例子中,一个Squirrel类被建模。它有一个名称和一个权重。现在你可以创建一个比较器类来使用这两个字段对它进行排序。所以首先按名称排序,然后按权重排序。类似于这样:

public class ChainingComparator implements Comparator<Squirrel> {
    public int compare(Squirrel s1, Squirrel s2) {

        Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies());
        c = c.thenComparingInt(s -> s.getWeight());

        return c.compare(s1, s2);
    }
}

到现在为止,一直都还不错。。但接下来是令人困惑的部分。在代码示例下面,它们声明您可以使用方法链接在一行中编写此代码。也许我误解了,但当我将比较部分和thencomparating部分链接起来时,我得到了一个编译错误。这与所比较对象的类型有关(首先是字符串,然后是int)。

为什么当我放入一个中间变量时它会工作,而当链接时它不会工作?那么,有没有可能连锁呢?

共有2个答案

路思源
2023-03-14

是的,这是可能的-链<代码>比较(…) 与<代码>然后比较(…) 和与比较(…) 使用方法引用而不是lambda表达式:

public int compare(Squirrel s1, Squirrel s2) {
    return Comparator.comparing(Squirrel::getSpecies)
        .thenComparing(Squirrel::getWeight)
        .compare(s1, s2);
}

为什么会这样?我无法比Brian在回答类似问题时解释得更好。

此外,这可以用1行重写(假设您有一个要排序的松鼠列表):

list.sort(Comparator.comparing(Squirrel::getSpecies).thenComparing(Squirrel::getWeight));
荆学民
2023-03-14

当您链接两者时,编译器无法推断返回的比较器的类型参数,因为它依赖于返回的比较器本身无法推断出来的比较器。

在lambda参数中指定comparing()(或使用方法引用)的类型,这样可以推断出comparing()的返回类型,从而解决推断问题:

    Comparator<Squirrel> c = Comparator.comparing((Squirrel s)  -> s.getSpecies())
                                       .thenComparingInt(s -> s.getWeight());

请注意,在lambda参数中指定类型,例如:

    Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies())
                                       .thenComparingInt((Squirrel s) -> s.getWeight());

将不起作用,因为在推理类型计算中未考虑接收方(此处为链式方法的返回类型)。

本JDK 8教程/文档很好地解释了这一点:

注意:需要注意的是,推理算法仅使用调用参数、目标类型和可能的明显理论收益类型来推断类型。推理算法不使用程序后期的结果。

 类似资料:
  • 我有一个ArrayList,需要按降序排序。我用java来实现它。util。流动流动排序(比较器)方法。以下是根据Java API的描述: 返回由该流的元素组成的流,根据提供的

  • 问题内容: 假设我有一对班 我希望先按第一个值排序,然后再按第二个值排序。现在,如果我这样做 一切正常,列表按对的第一个值排序,但是如果我这样做 它因错误而失败 好的,所以它可能无法推断参数,所以如果我这样做 它因错误而失败 为什么它对compare()而不是compare()。thenComparing()有效? 问题答案: 该错误似乎与的通用参数有关。一种解决方法是尝试使用显式类型: 请注意,

  • 我想用Lambda对列表排序: 但我得到了这个编译错误:

  • 假设我有一个双人课 我希望对它进行排序,首先是第一个值,然后是第二个值。现在,如果我这样做 一切都很好,列表按对的第一个值排序,但如果我这样做 它因错误而失败 好吧,所以它可能无法推断参数,所以如果我这样做 它因错误而失败 为什么它适用于comparing()而不适用于comparing()。然后比较()?

  • 问题内容: 用于比较的Python文档说: 可以任意链接比较,例如与等效,不同之处在于比较仅被评估一次(但在两种情况下都被发现为假,则根本不评估)。 所以像(人为的例子): 只要求输入一次。这很有道理。和这个: 仅询问 是否 介于1和10之间,并且仅打印“ woo!”。 if 也在10到20之间(证明它们可以“任意链接”)。这也是有道理的。 但是我仍然很好奇在lexer / parser / co

  • 问题内容: 我想知道Java链接器如何工作。具体来说,它将类,接口,包,方法等以何种顺序组合为jvm可执行格式。我在这里找到了一些信息,但是关于链接顺序的信息并不多。 问题答案: 没有Java“链接器”之类的东西。但是,存在类加载器的概念,该类加载器给出了“某处”中的java字节代码数组,可以创建类的内部表示形式,然后可以与etc 一起使用。 在这种情况下,接口只是特殊的类。加载类后,方法和字段将