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

 import java.util.Arrays;

 public class Client {
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);
} System.out.println("张 UNICODE:" + Integer.toHexString('张'));
System.out.println("李 UNICODE:" + Integer.toHexString('李'));
System.out.println("王 UNICODE:" + Integer.toHexString('王'));
}
}

对应输出:

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

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

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

     public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value; int k = 0;
while (k < lim) {
         //原字符串的字符数组
char c1 = v1[k];
         //比较字符串的字符数组
char c2 = v2[k];
if (c1 != c2) {
           //比较两者的char值大小
return c1 - c2;
}
k++;
}
return len1 - len2;
}

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

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

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

修改代码:

 import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale; public class Client {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
String[] strs = {"张三(Z)","李四(L)","王五(W)"};
//定义一个中文排序器
Comparator c = Collator.getInstance(Locale.CHINA);
//升序排列
Arrays.sort(strs,c);
int i=0;
for(String str:strs){
System.out.println((++i) + "、"+ str);
}
}
}

输出结果:

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

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

看代码:

 import java.text.Collator;
import java.util.Arrays;
import java.util.Locale; public class Client {
public static void main(String[] args) throws Exception {
String[] strs = {"犇(B)","鑫(X)"};
Arrays.sort(strs,Collator.getInstance(Locale.CHINA));
int i=0;
for(String str:strs){
System.out.println((++i) + "、"+ str);
}
}
}

代码输出:

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

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

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

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

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

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

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

[改善Java代码]对字符串排序 持一种宽容的心态的更多相关文章

  1. [改善Java代码]非稳定排序推荐使用List

    我们知道Set与List的最大区别就是Set中的元素不可以重复(这个重复指的equals方法的返回值相等),其他方面则没有太大的区别了,在Set的实现类中有一个比较常用的类需要了解一下:TreeSet ...

  2. [java代码库]-简易计算器(第二种)

    [java代码库]-简易计算器(第二种) 第二种方案:在程序中不使用if/switch……case等语句,完成计算器功能. <html> <head> <title> ...

  3. [改善Java代码]易变业务使用脚本语言编写

    建议16: 易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP.Ruby.Groovy.JavaScript等,这些“入侵者”都有一个共同特征:全是同一类语言—脚本语言,它们 ...

  4. [改善Java代码]警惕自增的陷阱

    建议7: 警惕自增的陷阱 老师就说:自增有两种形式,分别是i++和++i,i++表示的是先赋值后加1,++i是先加1后赋值,这样理解了很多年也没出现问题,直到遇到如下代码,我才怀疑我的理解是不是错了: ...

  5. [改善Java代码]推荐在复杂字符串操作中使用正则表达式

    一.分析  字符串的操作,诸如追加.合并.替换.倒序.分隔等,都是在编码过程中经常用到的,而且Java也提供了append.replace.reverse.split等方法来完成这些操作,它们使用起来 ...

  6. [改善Java代码]自由选择字符串拼接方法

    对一个字符串拼接有三种方法:加号,contact方法,StringBuffer或者StringBuilder的append方法,其中加号是最常用的.其他两种方式偶尔会出现在一些开源项目中,那么这三者有 ...

  7. [改善Java代码]减少HashMap中元素的数量

    在系统开发中我们经常会使用HashMap作为数据集容器,或者是用缓冲池来处理,一般很稳定,但偶尔也会出现内存溢出的问题(OutOfMemory错误),而且这经常是与HashMap有关的.而且这经常是与 ...

  8. [改善Java代码]不推荐使用binarySearch对列表进行检索

    对一个列表进行检索时,我们使用的最多的是indexOf方法,它简单好用,而且也不会出错,虽然它只能检索到第一个符合条件的值,但是我们可以生成子列表后再检索.这样也就可以查找到所有符合条件的值了. Co ...

  9. [改善Java代码]子列表只是原列表的一个视图

    List接口提供了subList方法,其作用是返回一个列表的子列表.这与String类的subString有点类似.但是他们的功能是否相同?看代码: import java.util.ArrayLis ...

随机推荐

  1. Visual Studio 2013智能提示失效解决办法

    各种解决VS2013智能提示失效办法: 1.重置所有设置    工具->导入导出设置->重置所有设置 2.智能提示开关: 工具->选项->文本编辑器->C#->常规 ...

  2. Struts2类型转换器

    概述 A .从一个HTML 表单到一个 Action 对象,类型转换是从字符串到非字符串.    –HTTP没有"类型" 的概念.每一项表单输入只可能是一个字符串或一个字符串数组. ...

  3. Spring入门(3)-Spring命名空间与Bean作用域

    Spring入门(3)-Spring命名空间与Bean作用域 这篇文章主要介绍Spring的命名空间和Bean作用域 0. 目录 Spring命名空间 Bean作用域 1. Spring命名空间 在前 ...

  4. hdu 5640 King's Cake(BestCoder Round #75)

    King's Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. OpenCDN2.0安装

    部署说明 为网站加速,建立私有的CDN节点群,每部署一个CDN节点只需5分钟,无节点数量上限!参考 http://ocdn.me/ 安装需求 OpenCDN的Beta版目前在CentOS5.x - C ...

  6. UVaLive 7360 Run Step (排列组合,枚举)

    题意:给定一个数 n ,表示一共有 n 步,然后你可以迈一步也可以迈两步,但是左腿和右腿的一步和两步数要一样,并且两步数不小于一步数,问你有多少种方式. 析:虽然是排列组合,但还是不会做.....水啊 ...

  7. 离散信号MATLAB频谱分析程序

    from http://blog.csdn.net/u012129372/article/details/26565611 %FFT变换,获得采样数据基本信息,时域图,频域图 %这里的向量都用行向量, ...

  8. Visual Studio 调用 Delphi DLL 会退出的解决方案

    新写了一个 Delphi 的 dll 供 C# 程序调用,却发现在使用 Visual Studio 2012 进行调试时,程序会在调用后自动退出. 经过对比,只需要将工程属性中“调试”一页下的“启用 ...

  9. Codeforces Round #334 (Div. 2) A. Uncowed Forces 水题

    A. Uncowed Forces Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/604/pro ...

  10. Codeforces Round #328 (Div. 2) B. The Monster and the Squirrel 打表数学

    B. The Monster and the Squirrel Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/c ...