Java 我可以使用Collections.sort和quasiorder吗?

Java 我可以使用Collections.sort和quasiorder吗?,java,sorting,comparator,preorder,Java,Sorting,Comparator,Preorder,全拟序(也称为全预序)是一种较弱的序关系,允许两个不同的元素被视为“大小相同”。例如,所有字符串的集合按长度进行准排序,因为两个不同的字符串可以具有相同的长度 现在假设我们有一个字符串列表,并希望按长度排序(最短优先)。如果两个字符串的长度相同,我们就不在乎哪个先到。 乍一看,写作似乎是合理的 Collections.sort(list, (s, t) -> s.length() - t.length()); 不幸的是,这是非法的。Comparator接口的Javadoc明确要求比较必须

全拟序(也称为全预序)是一种较弱的序关系,允许两个不同的元素被视为“大小相同”。例如,所有字符串的集合按长度进行准排序,因为两个不同的字符串可以具有相同的长度

现在假设我们有一个字符串列表,并希望按长度排序(最短优先)。如果两个字符串的长度相同,我们就不在乎哪个先到。 乍一看,写作似乎是合理的

Collections.sort(list, (s, t) -> s.length() - t.length());

不幸的是,这是非法的。Comparator接口的Javadoc明确要求比较必须实现总体排序。由于“a.length()-“b.length()等于0,但“a.equals”(“b”)为false,因此违反了此规则


那么,我们应该如何干净利落地做到这一点呢?我所说的干净是指不引入虚假的比较,例如通过哈希代码或自然排序。

使用长度的解决方案确实提供了

您所指的
“a”.length()-“b”.length()==0
,但
“a”.equals(“b”)==false
不是总排序。它必须与平等相一致。在这一点上,报告说:

比较器c对一组元素S施加的顺序称为与equals一致,当且仅当c.compare(e1,e2)==0具有与e1相同的布尔值。S中的每个e1和e2都具有equals(e2)


这并不意味着你必须提供一个与equals一致的比较器。

你误解了文档。当他们说

一种比较函数,它对某些对象集合施加总排序

这是定义,不是要求。对于给定的
比较器
c
,如果
c.compare(o1,o2)=0
,则就
c
定义的顺序而言,
o1
o2
是相等的


文档接着讨论了
比较器
与equals“一致”的含义,这基本上意味着
比较器
固有的平等感,如上所述,与允许对象的
equals()
方法固有的平等感相同。这种讨论的前提是,某些
比较器
可能不具备您提出的特性。使用这样的
比较器
来订购
分拣数据集
分拣地图
可能会产生违反这些接口契约的行为,但是将这样的
比较器
集合.sort()一起使用没有错“Comparator接口的Javadoc明确要求比较必须实现总体排序。“什么给你这样的印象?这是一个总排序;只是根据
,元素不相等。根据比较器,equals
可以相等。这不仅是合法的,而且是完全正常的。这根本不是“与equals一致”。我想你混淆了“总排序”和“严格的总排序”“与您的问题不太相关,但我们应该避免使用
s.length()-t.length()
作为比较的结果。的确,我们在处理正值时是安全的(如本例),但对于负值,结果可能从负值溢出到正值,这可能是一个问题。最好使用
Integer.compare(s.length(),t.length())
。顺便说一句,我们可以使用更清晰的比较器,而不是
(s,t)->整数。compare(s.length(),t.length())
比较器。comparingit(String::length)
@John Graham:总阶数必须满足反对称公理:如果是Ok,我就不必严格要求提供与equals一致的比较器。但如果我不这样做,我就会受到威胁:“当使用比较器对排序集(或排序映射)施加与等于不一致的排序时,应谨慎行事。如果c对S施加的排序与等于不一致,则排序集(或排序映射)的行为将“奇怪”。特别是排序集(或排序地图)将违反集合(或地图)的一般契约,该契约是用相等的术语定义的。“所以,我觉得它看起来很脏。谢谢,我开始怀疑这一点。我想你是对的。