Comparator.compareBoolean() 和 Comparator.compare() 一样吗?

nim*_*o23 7 comparator java-8

我怎么能写这个

Comparator <Item> sort = (i1, i2) -> Boolean.compare(i2.isOpen(), i1.isOpen());
Run Code Online (Sandbox Code Playgroud)

像这样(代码不起作用):

Comparator<Item> sort = Comparator.comparing(Item::isOpen).reversed();
Run Code Online (Sandbox Code Playgroud)

比较方法没有像 Comparator.comparingBool() 这样的东西。Comparator.comparing 返回 int 而不是“Item”。

Eug*_*ene 6

为什么不能这样写?

 Comparator<Item> sort = Comparator.comparing(Item::isOpen);
Run Code Online (Sandbox Code Playgroud)

下面Boolean.compareTo被称为,这反过来又是相同的Boolean.compare

public static int compare(boolean x, boolean y) {
    return (x == y) ? 0 : (x ? 1 : -1);
}
Run Code Online (Sandbox Code Playgroud)

而这个:Comparator.comparing returns int and not "Item".毫无意义,Comparator.comparing 必须返回一个Comparator<T>;在您的情况下,它正确返回一个Comparator<Item>.

  • @nimo23,我不会担心 lambda 是否比方法引用“更快”:您不太可能注意到差异,并且两个版本都受到运行时优化的影响,这使事情变得更加复杂。 (4认同)

Hol*_*ger 6

重载comparingIntcomparingLong和 的comparingDouble存在仅出于性能原因。它们在语义上与非专门化comparing方法相同,因此使用comparing代替comparingXXX具有相同的结果,但可能具有装箱开销,但实际含义取决于特定的执行环境。

\n\n

对于boolean值,我们可以预测开销可以忽略不计,因为该方法Boolean.valueOf将始终返回Boolean.TRUEorBoolean.FALSE且永远不会创建新实例,因此即使特定 JVM 无法内联整个代码,它也不依赖于是否存在优化器中的逃逸分析。

\n\n

正如您已经发现的,反转比较器是通过在内部交换参数来实现的,就像您在 lambda 表达式中手动执行的操作一样。

\n\n

请注意,仍然可以创建一个融合反转和未装箱比较的比较器,而无需重复表达式isOpen()

\n\n
Comparator<Item> sort = Comparator.comparingInt(i -> i.isOpen()? 0: 1);\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,正如所说,它\xe2\x80\x99 不太可能具有比该Comparator.comparing(Item::isOpen).reversed()方法显着更高的性能。

\n\n
\n\n

但请注意,如果您有boolean排序标准并关心最大性能,则可以考虑用桶排序变体替换通用排序算法。例如

\n\n

如果您有 Stream,请替换

\n\n
List<Item> result = /* stream of Item */\n    .sorted(Comparator.comparing(Item::isOpen).reversed())\n    .collect(Collectors.toList());\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
Map<Boolean,List<Item>> map = /* stream of Item */\n    .collect(Collectors.partitioningBy(Item::isOpen,\n                                       Collectors.toCollection(ArrayList::new)));\nList<Item> result = map.get(true);\nresult.addAll(map.get(false));\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,如果您有List,则替换

\n\n
list.sort(Comparator.comparing(Item::isOpen).reversed());\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
ArrayList<Item> temp = new ArrayList<>(list.size());\nlist.removeIf(item -> !item.isOpen() && temp.add(item));\nlist.addAll(temp);\n
Run Code Online (Sandbox Code Playgroud)\n\n

ETC。

\n