提高你的Java代码质量吧:中文字符串排序的瑕疵

一、分析 

在Java中一设计中文处理就会冒出很多问题来,其中排序也是一个让人头疼的课题 

我们知道Arrays工具类的默认排序是通过数组元素的compareTo方法来进行比较的,那我们来看String类的compareTo方法的主要实现: 

  1. while(k < lim){   
  2.     //原字符串的字符数组    
  3.     char c1 = v1[k];   
  4.     //比较字符串的字符数组    
  5.     char c2 = v2[k];   
  6.    
  7.     if(c1 != c2){   
  8.         //比较两者的char值大小    
  9.         return c1 - c2;   
  10.     }   
  11.     k++   
  12. }   
while(k < lim){ 
    //原字符串的字符数组 
    char c1 = v1[k]; 
    //比较字符串的字符数组 
    char c2 = v2[k]; 
 
    if(c1 != c2){ 
        //比较两者的char值大小 
        return c1 - c2; 
    } 
    k++ 
} 

它是先取得字符数组,然后一个一个地比较大小,注意这里是字符比较(减号操作符),也就是UNICODE码值比较 

二、场景 

我们看如下代码 

  1. public static void main(String[] args){   
  2.     String[] strs = {"张三(Z)","李四(L)","王五(W)"};   
  3.     //排序,默认是升序    
  4.     Arrays.sort(strs);   
  5.    
  6.     int i = 0;   
  7.     for(String str:strs){   
  8.         System.out.println((++i) + "、" + str);   
  9.     }   
  10. }   
public static void main(String[] args){ 
    String[] strs = {"张三(Z)","李四(L)","王五(W)"}; 
    //排序,默认是升序 
    Arrays.sort(strs); 
 
    int i = 0; 
    for(String str:strs){ 
        System.out.println((++i) + "、" + str); 
    } 
} 

结果 

1、张三(Z) 

2、李四(L) 

3、王五(W) 

由上面分析Arrays.sort()使用数组元素的compareTo方法进行比较,它比较字符数组的UNICODE码值,查下UNICODE代码表,"张"的码值是5F20,"李"是674E,这样一看,"张"排在"李"前面也就正确了。 

 

但是这与我们的意图冲突,这一点在JDK文档中也有说明:对于非英文的String排序,可能会出现不正确的情况 

那我们如何解决呢?Java推荐使用Collator类进行排序,代码修改如下 

  1. public static void main(String[] args)throws Exception{   
  2.     String[] strs = {"张三(Z)","李四(L)","王五(W)"};   
  3.     //定义一个中文排序器    
  4.     Comparator c = Collator.getInstance(Local.CHINA);   
  5.     //升序排列    
  6.     Arrays.sort(strs,c);   
  7.    
  8.     int i = 0;   
  9.     for(String str:strs){   
  10.         System.out.println((++i) + "、" + str);   
  11.     }   
  12. }   
public static void main(String[] args)throws Exception{ 
    String[] strs = {"张三(Z)","李四(L)","王五(W)"}; 
    //定义一个中文排序器 
    Comparator c = Collator.getInstance(Local.CHINA); 
    //升序排列 
    Arrays.sort(strs,c); 
 
    int i = 0; 
    for(String str:strs){ 
        System.out.println((++i) + "、" + str); 
    } 
} 

结果 

1、李四(L) 

2、王五(W) 

3、张三(Z) 

但是注意了,汉字有象行文字,音行分离。不是每个汉字都能按照拼音的顺序排序好的,如"犇"和"鑫"。 

三、建议 

如果是排序对象是经常使用的汉字,使用Collator类排序完全就可以满足我们的要求。如果需要严格排序,则需要使用一些开源的项目来实现了,比如pinyin4j可以把汉字转换为拼音,然后我们自己来实现排序算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值