首页 > 解决方案 > Java:将 Collection.sort 和 lambda 表达式与三元运算符结合使用会导致意外结果

问题描述

我有以下课程:

import java.util.*;

class ClassA {
    public static void main(String...args) {
        var list = new ArrayList<String>();
        list.add("test");
        list.add("abc");

        Collections.sort(list, (a, b) -> a.length() >= b.length() ? 1 : 0); // [test, abc]
        //Collections.sort(list, (a, b) -> a.compareTo(b));                 // [abc, test]

        System.out.println(list);
    }
}

我以为Collection.sort()会排序。我认为a.length()是 4 并且b.length()是 3 可以评估为(4 >= 3)真的。所以a.length() >= b.length() ? 1 : 0会返回 1 并表示"test"大于"abc"。所以它应该像[abc, test].

但是我只有在[abc, test]将代码更改为 时才能得到结果a.length() >= b.length() ? 1 : -1,这似乎表明a.length() >= b.length()计算结果为false. 这是为什么?

为什么第一个 lambda 表达式导致[test, abc],而修改后的版本导致[abc, test]

Collections.sort(list, (a, b) -> a.compareTo(b));像预期的那样工作。

标签: java

解决方案


阅读Comparator:的文档compare,或者你用来实现它的 lambda,必须返回一个负值 if a < b,而不仅仅是一个正值 if a > b。如果a等于(或比较等于),它也必须返回零b。这与其他一些编程语言的期望不同,我认为这让你感到困惑。

永远不要关注积极的输出,只关注消极的输出,这将是一个完全有效的实现sort。看起来它没有按照您预期的顺序进行比较。

您可以将这个比较器正确地实现为(a, b) -> Integer.compare(a.length(), b.length()),或者更简单地实现为Comparator.comparingInt(String::length)


推荐阅读