自然排序
怎么排序
有一个文件夹,里面有一堆图片,漫画浏览器需要知道哪个是第一张,哪个是第二张,对于压缩包也是这样。这就是个排序问题。
我用的方法就是直接Arrays.sort(array)
或者Collections.sort(list)
,也就是直接使用 String 中 char 的值来进行排序。
在图片命名即为规范的情况下,这是没有问题的。譬如:
0001.jpg
0002.jpg
0003.jpg
然而在其他情况下就会出问题。譬如:
nazo-no-kanojo-ekkusu-1.jpg
nazo-no-kanojo-ekkusu-11.jpg
nazo-no-kanojo-ekkusu-2.jpg
显然,nazo-no-kanojo-ekkusu-2.jpg
应该排在nazo-no-kanojo-ekkusu-11.jpg
前面的,而该排序算法做不到这点。问题出在了数字部分的比较。用户不可能按照理想情况,来对数字用零填充,使所有数字位数相同。那么需要对字符串中的数字部分单独处理。
自然排序
Windows Explorer 文件排序的默认效果符合我的期望。Microsoft 官方称其为 Numerical Sorting
。然而网络中常见的称呼是 Natural Sorting
,姑且称之为自然排序
。其实现方法也很简介,首先将字符串切分,分为全数字字符串与其他,再各部分一一对应比较,若皆为全数字字符串,则比较其值,否则按字符比较。
Java 实现
StackOverflow 上 wumpz 给出了一种实现方法。这个实现方法相比之前的描述要丰富了许多,譬如加入了对空格
与.
的特殊处理。不过还是有几处值得优化的地方。
- 切分字符串时还应排除空字符串
- 切分字符串没必要一次性完成,而是可以边切分边比较
- 切分字符串较为简单,不必使用正则表达式
- 数字字符串的判断不要利用异常判断
将其优化之后的代码是这样的:
缺陷
在某些情况自然排序也会导致糟糕的排序,譬如文件名中有小数,或者十六进制数。
参考
https://technet.microsoft.com/en-us/library/hh475812.aspx
http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting
https://stackoverflow.com/questions/23205020/java-sort-strings-like-windows-explorer