Comparator.compareBoolean()与Comparator.compare()相同?

时间:2017-08-29 14:31:49

标签: java-8 comparator

我该怎么写这个

Comparator <Item> sort = (i1, i2) -> Boolean.compare(i2.isOpen(), i1.isOpen());

这样的事情(代码不起作用):

Comparator<Item> sort = Comparator.comparing(Item::isOpen).reversed();

比较方法没有像Comparator.comparingBool()那样的东西。 Comparator.comparing返回int而不是&#34; Item&#34;。

3 个答案:

答案 0 :(得分:2)

为什么你不能这样写呢?

 Comparator<Item> sort = Comparator.comparing(Item::isOpen);

调用Boolean.compareTo下面的内容,后者与Boolean.compare

相同
public static int compare(boolean x, boolean y) {
    return (x == y) ? 0 : (x ? 1 : -1);
}

而且:Comparator.comparing returns int and not "Item".没有意义,Comparator.comparing 必须返回Comparator<T>;在您的情况下,它正确返回Comparator<Item>

答案 1 :(得分:2)

使用关键提取器参数进行比较:

Comparator<Item> comparator = 
    Comparator.comparing(Item::isOpen, Boolean::compare).reversed();

答案 2 :(得分:1)

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

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

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

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

Comparator<Item> sort = Comparator.comparingInt(i -> i.isOpen()? 0: 1);

但是,如上所述,它不太可能比Comparator.comparing(Item::isOpen).reversed()方法具有更高的性能。

但请注意,如果您有boolean排序条件并且关注最高性能,则可以考虑使用存储桶排序变量替换通用排序算法。 E.g。

如果您有Stream,请替换

List<Item> result = /* stream of Item */
    .sorted(Comparator.comparing(Item::isOpen).reversed())
    .collect(Collectors.toList());

Map<Boolean,List<Item>> map = /* stream of Item */
    .collect(Collectors.partitioningBy(Item::isOpen,
                                       Collectors.toCollection(ArrayList::new)));
List<Item> result = map.get(true);
result.addAll(map.get(false));

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

list.sort(Comparator.comparing(Item::isOpen).reversed());

ArrayList<Item> temp = new ArrayList<>(list.size());
list.removeIf(item -> !item.isOpen() && temp.add(item));
list.addAll(temp);