对字符串排序 持一种宽容的心态

简介:

在Java中一涉及到中文处理就会冒出很多的问题来,其中的排序也是一个让人头疼的问题,看代码:

复制代码
 1 import java.util.Arrays;
 2 
 3 public class Client {
 4     public static void main(String[] args){
 5         String[] strs = {"张三(Z)","李四(L)","王五(W)"};
 6         //排序,默认是升序
 7         Arrays.sort(strs);
 8         int i=0;
 9         for(String str:strs){            
10             System.out.println((++i) + "、"+ str);
11         }
12     
13         System.out.println("张 UNICODE:" + Integer.toHexString('张'));
14         System.out.println("李 UNICODE:" + Integer.toHexString('李'));
15         System.out.println("王 UNICODE:" + Integer.toHexString('王'));
16     }
17 }
复制代码

 对应输出:

复制代码
1、张三(Z)
2、李四(L)
3、王五(W)
张 UNICODE:5f20
李 UNICODE:674e
王 UNICODE:738b
复制代码

 

我们希望是按照拼音升序排列,即为李四,王五,张三,但是结果却不是这样的.

这是按照什么进行排序的?Arrays工具类默认的排序是通过数组元素的compareTo()方法排序的,看其源代码实现:

复制代码
 1     public int compareTo(String anotherString) {
 2         int len1 = value.length;
 3         int len2 = anotherString.value.length;
 4         int lim = Math.min(len1, len2);
 5         char v1[] = value;
 6         char v2[] = anotherString.value;
 7 
 8         int k = 0;
 9         while (k < lim) {
//原字符串的字符数组
10 char c1 = v1[k];
//比较字符串的字符数组
11 char c2 = v2[k]; 12 if (c1 != c2) {
//比较两者的char值大小
13 return c1 - c2; 14 } 15 k++; 16 } 17 return len1 - len2; 18 }
复制代码

 

上面代码先取得字符串的字符数组,然后一个个的比较大小,注意这里是字符比较(减号操作符),也就是UNICODE码值的比较,查UNICODE表,

"张"的码值是5F20,而"李"是674E,这样看"张"排在"李"前面也就很正确了.

这点在JDK文档中也有说明:对于非英文的String排序可能会出现不准确的情况,那该如何解决这个问题?Java推荐使用Collator类进行排序.

修改代码:

复制代码
 1 import java.text.Collator;
 2 import java.util.Arrays;
 3 import java.util.Comparator;
 4 import java.util.Locale;
 5 
 6 public class Client {
 7     @SuppressWarnings("unchecked")
 8     public static void main(String[] args) throws Exception {
 9         String[] strs = {"张三(Z)","李四(L)","王五(W)"};
10         //定义一个中文排序器
11         Comparator c = Collator.getInstance(Locale.CHINA);
12         //升序排列
13         Arrays.sort(strs,c);
14         int i=0;
15         for(String str:strs){
16             System.out.println((++i) + "、"+ str);
17         }
18     }
19 }
复制代码

 

输出结果:

1、李四(L)
2、王五(W)
3、张三(Z)

 

汉字博大精深,最主要的一点是汉字 有象形文字,音行分离,并不是每个汉字都能按照拼音的顺序排列好.

看代码:

复制代码
 1 import java.text.Collator;
 2 import java.util.Arrays;
 3 import java.util.Locale;
 4 
 5 public class Client {
 6     public static void main(String[] args) throws Exception {
 7         String[] strs = {"犇(B)","鑫(X)"};
 8         Arrays.sort(strs,Collator.getInstance(Locale.CHINA));
 9         int i=0;
10         for(String str:strs){
11             System.out.println((++i) + "、"+ str);
12         }
13     }
14 }
复制代码

代码输出:

1、鑫(X)
2、犇(B)

 输出结果又乱了,只是因为汉字的文化博大精深.

更深层次的原因是Java使用的是UNICODE编码,而中文UNICODE字符集是源于GB18030的,GB18030又是从GB2312发展起来的,GB2312是一个包含了7000多个字符的字符集,它是按照拼音排序,并且是连续的.

之后的GBK,GB18030都是在其基础上扩充起来的.

如果是排序对象是经常使用的汉字,使用Collator类排序完全可以满足我们的需求.毕竟GB2312已经包含了大部分的汉字,如果需要严格排序,则要使用一些开源项目来自己实现了.

比如pinyon4j可以把汉字转换为拼音.然后我们自己来实现排序算法,不过此时也要考虑诸如算法,同音字,多音字等众多问题.

 

如果排序不是一个关键算法,使用Collator类即可.

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5660273.html,如需转载请自行联系原作者

相关文章
|
2月前
|
Java
当Java数据类型遇上“爱情”,会擦出怎样的火花?
当Java数据类型遇上“爱情”,会擦出怎样的火花?
48 1
|
12月前
aviator 属实搞事情
aviator 属实搞事情
84 0
四道好题分享(看似简单,但是棘手)
四道好题分享(看似简单,但是棘手)
97 0
|
机器学习/深度学习 安全 测试技术
郑轻22级新生C语言周赛(3)——命题人:宋江、张永林、张纪龙复盘
郑轻22级新生C语言周赛(3)——命题人:宋江、张永林、张纪龙复盘
66 0
|
供应链
MECE 法则在职场中的常见用法
MECE法则,是麦肯锡咨询顾问芭芭拉·明托在《金字塔原理》中提出的一个思考工具,它的英文缩写是Mutually Exclusive Collectively Exhaustive,意思是“相互独立,完全穷尽”,也就是不重不漏的意思。
271 0
MECE 法则在职场中的常见用法
|
存储 SQL 缓存
震惊,99.9% 的同学没有真正理解字符串的不可变性
稍有些基础的同学都知道 Java 中 String 字符串是“不可变”的,想要使用“可变字符串”可以使用 `StringBuilder` 和 `StringBuffer` 。 大多数讲字符串不可变性的文章大同小异。但实际上大多数人的理解并不对。
164 0
震惊,99.9% 的同学没有真正理解字符串的不可变性
|
Java C++
新来的实习妹纸被老大骂了,因为她自己写了将字符串转换为整数的工具。。。
新来的实习妹纸被老大骂了,因为她自己写了将字符串转换为整数的工具。。。
113 0
新来的实习妹纸被老大骂了,因为她自己写了将字符串转换为整数的工具。。。
|
存储 算法
蛋蛋惨遭数组滑铁卢,面试官建议回村养猪。
蛋蛋惨遭数组滑铁卢,面试官建议回村养猪。
蛋蛋惨遭数组滑铁卢,面试官建议回村养猪。
|
设计模式 运维 搜索推荐
都是血泪,程序员傍身的生存法则(上)
都是血泪,程序员傍身的生存法则(上)
158 0
都是血泪,程序员傍身的生存法则(上)
|
存储 Java 程序员
面试官刁难:Java字符串可以引用传递吗?(1)
面试官刁难:Java字符串可以引用传递吗?
135 0
面试官刁难:Java字符串可以引用传递吗?(1)