对于某些字符串,使用基本字符比较进行sortWith失败

时间:2018-07-21 02:25:40

标签: java scala sorting

我要应用自定义排序comparator,如下所示:

 myString.sortWith{ case (c1,c2) => c1.compareTo(c2) <= 0}

应该按其代码点值对字符串的字符进行排序。

但是它并不总是有效。请考虑一个简单的字符串cab312

val str = "cab312"

str.sortWith{ case (c1,c2) => c1.compareTo(c2) <= 0}
res0: String = 123abc

那很好。考虑一个更复杂的字符串:

scala> val str = "TOADS POOLS hoppin good service & repair"
str: String = TOADS POOLS hoppin good service & repair

scala> str.sortWith{ case (c1,c2) => c1.compareTo(c2) <= 0}
java.lang.IllegalArgumentException: Comparison method violates its general contract!
  at java.util.TimSort.mergeHi(TimSort.java:899)
  at java.util.TimSort.mergeAt(TimSort.java:516)
  at java.util.TimSort.mergeCollapse(TimSort.java:441)
  at java.util.TimSort.sort(TimSort.java:245)
  at java.util.Arrays.sort(Arrays.java:1438)
  at scala.collection.SeqLike$class.sorted(SeqLike.scala:648)
  at scala.collection.immutable.StringOps.sorted(StringOps.scala:29)
  at scala.collection.SeqLike$class.sortWith(SeqLike.scala:601)
  at scala.collection.immutable.StringOps.sortWith(StringOps.scala:29)
  ... 32 elided

所以..我们得到一个java.lang.IllegalArgumentException: Comparison method violates its general contract!

这是怎么回事?相同的comparator怎样才能成功和失败。这是timsort中的错误吗?在任何情况下,都有解决方法吗?

1 个答案:

答案 0 :(得分:3)

文档明确指出,sortWith期望有一个函数lt,当且仅当第一个操作数出现(严格是 L ess T han )第二个操作数:

  

lt 比较函数,用于测试其第一个参数是否以所需顺序在其第二个参数之前。

您的true对于相等的元素返回true,因此违反了c1.compareTo(c2) <= 0的约定。将lt更改为<=可解决以下问题:

<