遇到了一个对包含中文的字符串进行排序的问题. 要求按 unicode 编码对字符串进行排序.
测试字符串数组如下:
- String[] arr = {
- "1 - 测试",
- "1 - 编辑",
- "1 - 营销",
- "1 结束",
- "2 - 测试",
- "1-qt"
- };
按 unicode 排序的期望结果应该是这样的:
1 - 编辑, 1 - 测试, 1 - 营销, 1-qt, 1 结束, 2 - 测试
先按 java.lang.String 类提供的默认比较方案进行实现, 大致如下:
- import java.util.Arrays;
- import java.util.Comparator;
- public class MyJob {
- public static void main(String[] args) {
- String[] arr = {
- "1 - 测试",
- "1 - 编辑",
- "1 - 营销",
- "1 结束",
- "2 - 测试",
- "1-qt"
- };
- Comparator<String> c = 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 来改造之前的代码:
- import java.text.Collator;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.Locale;
- public class MyJob {
- public static void main(String[] args) {
- String[] arr = {
- "1 - 测试",
- "1 - 编辑",
- "1 - 营销",
- "1 结束",
- "2 - 测试",
- "1-qt"
- };
- Comparator<String> c = (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 对 Unicode Collation Algorithm(UCA,Unicode 整理算法) 的支持并不好.
此时可以考虑使用 IBM ICU 提供的 Collator 来替换 jdk 默认的 Collator. 代码如下:
- import com.ibm.icu.text.Collator;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.Locale;
- public class MyJob {
- public static void main(String[] args) {
- String[] arr = {
- "1 - 测试",
- "1 - 编辑",
- "1 - 营销",
- "1 结束",
- "2 - 测试",
- "1-qt"
- };
- Comparator<String> c = (o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1, o2);
- Arrays.sort(arr, c);
- System.out.println(Arrays.toString(arr));
- }
- }
相关的依赖为:
- <dependency>
- <groupId>com.ibm.icu</groupId>
- <artifactId>icu4j-localespi</artifactId>
- <version>60.2</version>
- </dependency>
执行结果为:
[1 - 编辑, 1 - 测试, 1 - 营销, 1-qt, 1 结束, 2 - 测试]
可以看到是和预期一致的.
参考文档
- Java Unicode strings sorting
- ICU User Guide - JNI http://userguide.icu-project.org/usefrom/jni
- ##########
来源: http://www.tuicool.com/articles/MNjyQz2