我该怎么写这个
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;。
答案 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)
重载comparingInt
,comparingLong
和comparingDouble
仅出于性能原因而存在。它们在语义上与非专用comparing
方法相同,因此使用comparing
而不是comparingXXX
具有相同的结果,但可能具有装箱开销,但实际含义取决于特定的执行环境。
如果值为boolean
,我们可以预测开销可以忽略不计,因为方法Boolean.valueOf
将始终返回Boolean.TRUE
或Boolean.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);
等