Java 中文字符按Unicode排序的实现方法
遇到了一个对包含中文的字符串进行排序的问题。要求按unicode编码对字符串进行排序。
测试字符串数组如下:
String[]arr={ "1-测试", "1-编辑", "1-营销", "1结束", "2-测试", "1-qt" };
按unicode排序的期望结果应该是这样的:
1-编辑,1-测试,1-营销,1-qt,1结束,2-测试
先按java.lang.String类提供的默认比较方案进行实现,大致如下:
importjava.util.Arrays; importjava.util.Comparator; publicclassMyJob{ publicstaticvoidmain(String[]args){ String[]arr={ "1-测试", "1-编辑", "1-营销", "1结束", "2-测试", "1-qt" }; Comparatorc=String::compareTo; Arrays.sort(arr,c); System.out.println(Arrays.toString(arr)); } }
结果如下:
[1-qt,1-测试,1-编辑,1-营销,1结束,2-测试]
可以看到中文字符不能按照拼音进行排序。这时最直接的思路就是将中文字符转为拼音后再进行排序。但是要注意下,在这里面有个字符串不包含中文字符,这就容易导致顺序混乱。
如下面这几个字符串按拼音进行排序顺序如下:
1-编辑,1-测试,1-qt,1-营销
可以看到字符串“1-qt”的位置出错了。但是按拼音来说它的位置又是对的。这不能不说是一个让人有些头疼的地方。
不过不用担心,java提供了java.text.Collator类来支持规范化的字符串比较。
使用Collator来改造之前的代码:
importjava.text.Collator; importjava.util.Arrays; importjava.util.Comparator; importjava.util.Locale; publicclassMyJob{ publicstaticvoidmain(String[]args){ String[]arr={ "1-测试", "1-编辑", "1-营销", "1结束", "2-测试", "1-qt" }; Comparatorc=(o1,o2)->Collator.getInstance(Locale.CHINESE).compare(o1,o2); Arrays.sort(arr,c); System.out.println(Arrays.toString(arr)); } }
改造后的程序执行排序的结果如下:
[1-qt,1-编辑,1-测试,1结束,1-营销,2-测试]
结果看着好像还OK。但是停停、注意下、字符串“1结束”的位置好像比较奇妙,理想情况下它应该在“1-营销”的后面。
这里出问题的原因我没有弄清楚。猜测着应该是java在Chinese语法中将中划线处理为空字符了。不过最根本的问题还是java对UnicodeCollationAlgorithm(UCA,Unicode整理算法)的支持并不好。
此时可以考虑使用IBMICU提供的Collator来替换jdk默认的Collator。代码如下:
importcom.ibm.icu.text.Collator; importjava.util.Arrays; importjava.util.Comparator; importjava.util.Locale; publicclassMyJob{ publicstaticvoidmain(String[]args){ String[]arr={ "1-测试", "1-编辑", "1-营销", "1结束", "2-测试", "1-qt" }; Comparatorc=(o1,o2)->Collator.getInstance(Locale.CHINESE).compare(o1,o2); Arrays.sort(arr,c); System.out.println(Arrays.toString(arr)); } }
相关的依赖为:
com.ibm.icu icu4j-localespi 60.2
执行结果为:
[1-编辑,1-测试,1-营销,1-qt,1结束,2-测试]
可以看到是和预期一致的。
总结