zoukankan      html  css  js  c++  java
  • [改善Java代码]对字符串排序 持一种宽容的心态

    在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类即可.

  • 相关阅读:
    刘翔那点事
    网站建站模板
    搞笑!from 饮水思源
    我de虚拟经济学系列第一章 经济危机拼命建桥
    IT民工系列——c#操作Microsoft IE,实现自动登录吧!
    商业智能的发展及其应用
    我de虚拟经济学系列第三章 常见的致富之路
    IT民工系列——c#操作EditGrid,自己做一个在线Excel数据库吧!
    Asp.net下的Singleton模式
    asp.net 控件功能小结
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5660273.html
Copyright © 2011-2022 走看看