【发布时间】:2015-10-13 21:30:50
【问题描述】:
全准序(也称为全预序)是一种较弱的排序关系,允许两个不同的元素被认为是“相同大小”。例如,所有字符串的集合是按长度准排序的,因为两个不同的字符串可以具有相同的长度。
现在假设我们有一个字符串列表,我们想按长度排序(最短的优先)。如果两个字符串的长度相同,我们不关心哪个先出现。 乍一看,这样写似乎是合理的
Collections.sort(list, (s, t) -> s.length() - t.length());
很遗憾,这是非法的。 Comparator 接口的 Javadoc 明确要求比较必须实现总排序。这是违反的,因为 "a".length() - "b".length() 等于 0,但 "a".equals("b") 为假。
那么,我们应该如何干净地做到这一点?干净地说,我的意思是不引入虚假的比较,例如通过哈希码或自然排序。
【问题讨论】:
-
"Comparator 接口的 Javadoc 明确要求比较必须实现全排序。" 是什么给您这样的印象?这是一个总排序;只是根据
.equals不相等的元素可以根据比较器相等。这不仅合法,而且完全正常。它根本不是“与equals一致”。 -
我认为您混淆了“总排序”和“严格总排序”
-
与您的问题无关,但我们应该避免使用
s.length() - t.length()作为比较的结果。确实,在处理正值时我们是安全的(就像在这种情况下),但是对于负值,结果可能会从负值溢出到正值,这可能是一个问题。最好改用Integer.compare(s.length(), t.length())。顺便说一句,我们可以使用更清晰的Comparator.comparingInt(String::length),而不是(s, t) -> Integer.compare(s.length(), t.length())。 -
@John Graham:总顺序必须满足反对称公理:如果 a
标签: java sorting comparator preorder