如何自定义Collections.sort()以按其数字前缀的顺序对字符串进行排序

时间:2016-11-27 16:52:20

标签: java sorting

我的List<String>包含以下值:

  

[1h,0h,2h,10h,4h,9h,3h,7h,8h,6h,5h]

当我使用Collections.sort()对其进行排序时,订单变为:

  

[0h,10h,1h,2h,3h,4h,5h,6h,7h,8h,9h]

相反,它应该是:

  

[0h,1h,2h,3h,4h,5h,6h,7h,8h,9h,10h]

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

您在问题中引用的输出是正常的。如果您查看Collection.sort的API说明,您会看到:

  

根据元素的自然顺序,将指定列表按升序排序。列表中的所有元素都必须实现Comparable接口。此外,列表中的所有元素必须是可相互比较的(即,e1.compareTo(e2)不得对列表中的任何元素e1和e2抛出ClassCastException。)

按照自然顺序,它们表示由compareTo - 方法指定的排序(接口Comparable只有方法compareTo),它告诉this - 对象是与排序中作为参数传递的对象相比,更大(返回严格正整数),或者等于(返回0),更少(返回严格的负整数)。要知道对象a是否应该在对象b之前获取,它只需调用a.compareTo(b)

  • 如果结果是严格肯定的(&gt; 0),则sort方法会在排序后的数组中a之后设置b
  • 如果结果是严格否定(&lt; 0),则sort方法会在排序数组中的a之前设置b
  • 如果结果为0,则sort方法不会更改它们的顺序。

我会参考the API of the compareTo method in the String class,详细解释了如何排序字符串以及方法返回的内容。
它的作用是在每个字符串上迭代每个字符的字符,并比较相同位置的字符,直到找到差异。如果在那个差异,this - 字符串的字符具有更高的Unicode value,它将返回严格的正整数(this纵梁更大)否则它将返回严格的负数整数(this - 字符串低于参数)。如果没有找到差异,它将返回0(this - 字符串,并且参数具有相同的“订单值”)。
现在你的情况(以及许多第一次订购字符串的人)的问题是整数不能与Unicode排序一起排序,因为它按字符每个字符。如果必须对String s1 = "19"String s2 = "1119"进行排序,则会调用s1.compareTo(s2)。第一个区别是第二个字符s19s2在该位置有1。由于 1位于Unicode表格中9之前1的值为十六进制值31且9具有十六进制值39),{{ 1}}将返回一个严格的正整数(请参阅API的链接以查看哪个值)。因此即使s1.compareTo(s2) ,它也会在排序数组中s2之前放置s1

所以现在你知道为什么会这样排序,让我们看看我们有什么解决方案:

  1. Map使用Integer.parseInt方法将数组元素转换为其开始部分的十进制值,对这些十进制值进行排序,并将生成的排序数组映射回原始元素。我不会真的推荐这个解决方案,因为额外的集合和由于映射而产生的额外代码。
  2. 创建您自己的Comparator-object,在那里指定您希望如何排序字符串(例如使用Integer.parseInt方法)并将其作为参数传递给Collections.sort方法。通过将其作为参数传递,您可以告诉sort方法使用您的1119 > 19 - 对象而不是经典的Comparator方法。 This link显示了如何使用compareTo对数组进行排序。它与使用它来对arraylist进行排序完全相同。
  3. 希望它有所帮助!

    祝你好运