1.前言

  对于包含汉字的字符串来说,排序的方式主要有两种:

    一种是拼音,一种是笔画。

  本文就讲述如何实现按拼音排序的比较器(Comparator)。

  作者:Jeff 发表于:2007年12月21日 11:27 最后更新于: 2007年12月21日 12:38 
  版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
  http://www.blogjava.net/jeff-lau/archive/2007/12/21/169257.html

2.拼音排序

  拼音有好几种方式,其中最主要的是中华人民共和国的汉语拼音 Chinese Phonetic。对汉字的排序有两种:一种是宽松的,能够按拼音排序最常用的汉字,另一种是严格的,能够按拼音排序绝大部分大部分汉字。

2.1宽松的拼音排序法

  原理:汉字最早是GB2312编码,收录了六千多个汉字,是按拼音排序的,编码是连续的。 后来出现了GBK编码,对GB2312进行了扩展,到了两万多汉字,并且兼容GB2312,也就是说GB2312中的汉字编码是原封不动搬到GBK中的(在GBK编码中[B0-D7]区中)。

  如果只关心这6000多个汉字的顺序,就可以用下面的方法实现汉字宽松排序。

 /**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/ package chinese.utility; import java.text.Collator;
import java.util.Comparator;
import java.util.Locale; public class PinyinSimpleComparator implements Comparator<String> {
public int compare(String o1, String o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
}
}

  在对[孙, 孟, 宋, 尹, 廖, 张, 徐, 昆, 曹, 曾,怡]这几个汉字排序,结果是:[曹, 昆, 廖, 孟, 宋, 孙, 徐, 尹, 曾, 张, 怡]。最后一个 怡 有问题,不该排在最后的。

注意:这个程序有两个不足

  • 由于gb2312中的汉字编码是连续的,因此新增加的汉字不可能再按照拼音顺序插入到已有的gb2312编码中,所以新增加的汉字不是按拼音顺序排的。
  • 同音字比较的结果不等于0 。

  下面的测试代码可以证明

 /**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/ /**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") > );
} /**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") != );
}

2.2严格的拼音排序法

  为了解决宽松的拼音的两点不足,可以通过实现汉语拼音的函数来解决。goolge下看到sf上有个pinyin4j的项目,可以解决这个问题,pinyin4j的项目地址是:http://pinyin4j.sourceforge.net/

  实现代码:

 /**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility; import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper; public class PinyinComparator implements Comparator<String> { public int compare(String o1, String o2) { for (int i = ; i < o1.length() && i < o2.length(); i++) { int codePoint1 = o1.charAt(i);
int codePoint2 = o2.charAt(i); if (Character.isSupplementaryCodePoint(codePoint1)
|| Character.isSupplementaryCodePoint(codePoint2)) {
i++;
} if (codePoint1 != codePoint2) {
if (Character.isSupplementaryCodePoint(codePoint1)
|| Character.isSupplementaryCodePoint(codePoint2)) {
return codePoint1 - codePoint2;
} String pinyin1 = pinyin((char) codePoint1);
String pinyin2 = pinyin((char) codePoint2); if (pinyin1 != null && pinyin2 != null) { // 两个字符都是汉字
if (!pinyin1.equals(pinyin2)) {
return pinyin1.compareTo(pinyin2);
}
} else {
return codePoint1 - codePoint2;
}
}
}
return o1.length() - o2.length();
} /**
* 字符的拼音,多音字就得到第一个拼音。不是汉字,就return null。
*/
private String pinyin(char c) {
String[] pinyins = PinyinHelper.toHanyuPinyinStringArray(c);
if (pinyins == null) {
return null;
}
return pinyins[];
}
}

3.测试

 /**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test; import java.util.Comparator; import org.junit.Assert;
import org.junit.Test; import chinese.utility.PinyinComparator; public class PinyinComparatorTest { private Comparator<String> comparator = new PinyinComparator(); /**
* 常用字
*/
@Test
public void testCommon() {
Assert.assertTrue(comparator.compare("孟", "宋") < );
} /**
* 不同长度
*/
@Test
public void testDifferentLength() {
Assert.assertTrue(comparator.compare("他奶奶的", "他奶奶的熊") < );
} /**
* 和非汉字比较
*/
@Test
public void testNoneChinese() {
Assert.assertTrue(comparator.compare("a", "阿") < );
Assert.assertTrue(comparator.compare("", "阿") < );
} /**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") < );
} /**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") == );
} /**
* 多音字(曾)
*/
@Test
public void testMultiSound() {
Assert.assertTrue(comparator.compare("曾经", "曾迪") > );
} }

  这样严格的拼音排序还是有有待改进的地方,看上面测试代码的最后一个测试,就会发现:程序不会根据语境来判断多音字的拼音,仅仅是简单的取多音字的第一个拼音。

Java汉字排序(2)按拼音排序的更多相关文章

  1. Android实现中文汉字笔划(笔画)、中文拼音排序、英文排序

    发布时间:2018-11-16   技术:Android   概述 最近要做一个类似微信的,在登录界面选择国家地区的功能,微信有中文汉字笔画排序以及中文拼音排序等几种方式,如下所示: 简体中文 拼音排 ...

  2. MySQL按照汉字的拼音排序

    按照汉字的拼音排序,用的比较多是在人名的排序中,按照姓氏的拼音字母,从A到Z排序: 如果存储姓名的字段采用的是GBK字符集,那就好办了,因为GBK内码编码时本身就采用了拼音排序的方法(常用一级汉字37 ...

  3. oracle表字段为汉字,依据拼音排序

    在order by后面使用NLSSORT函数转化汉字列,如下 select * from student order by NLSSORT(name,'NLS_SORT=SCHINESE_PINYIN ...

  4. MySQL按照汉字的拼音排序,mysql汉字排序

    按照汉字的拼音排序,用的比较多是在人名的排序中,按照姓氏的拼音字母,从A到Z排序: 如果存储姓名的字段采用的是GBK字符集,那就好办了,因为GBK内码编码时本身就采用了拼音排序的方法(常用一级汉字37 ...

  5. MySQL按照汉字的拼音排序(转)

    按照汉字的拼音排序,用的比较多是在人名的排序中,按照姓氏的拼音字母,从A到Z排序: 如果存储姓名的字段采用的是GBK字符集,那就好办了,因为GBK内码编码时本身就采用了拼音排序的方法(常用一级汉字37 ...

  6. MySQL按照汉字的拼音排序、按照首字母分类

    项目中有时候需要按照汉字的拼音排序,比如联系人列表.矿物分类等,有的还需要按拼音字母从A到Z分类显示. 如果存储汉字的字段编码使用的是GBK字符集,因为GBK内码编码时本身就采用了拼音排序的方法(常用 ...

  7. TP5 按照汉字的拼音排序

    业务需求:接口返回一个列表,但是这个列表要求按一定的条件排序,条件如下: 1,某字段(field1)为null的排前面 2,某字段(field2)为null的排前面 3,姓名(field3)按照汉字的 ...

  8. [转]Java汉字按照拼音排序

    最近项目上使用到汉字排序的问题,网上搜索了一下后普遍使用下面的方法比较. @Test public void test_sort_pinyin() { Collator cmp = Collator. ...

  9. Java汉字排序(3)按笔划排序

    对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画. 本文就讲述如何实现按笔划排序的比较器(Comparator). 作者:Jeff 发表于:2007年12月21日 11:27 最 ...

随机推荐

  1. Cassandra1.2文档学习(13)—— 数据读取

    参考文档:http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/dml/dml_about_ ...

  2. htmlcleaner

    String xpath = "//div"; Object[] myNodes = node.evaluateXPath(xpath); for (Object obj : my ...

  3. PHP网页的工作原理

    网络基本概念 IP地址 唯一标识网络上的主机或设备. IP地址是由四段8位二进制构成,中间用小数点隔开.如:192.168.18.70 每一段取值0-255的十进制. 特殊的IP地址:127.0.0. ...

  4. 【EF】疑难杂症

    用户和购物车数据  主从表 添加 ADO.NET实体数据类型 [Test] public void EntiyConnect() { var context = new projectDatabase ...

  5. 【BZOJ 1013】 [JSOI2008]球形空间产生器sphere

    Description 有一个球形空间产生器能够在n维空间中产生一个坚硬的球体.现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁 ...

  6. python学习笔记2(变量)

    变量是只不过保留的内存位置用来存储值,这意味着,当创建一个变量,那么它在内存中保留一些空间. Python是弱类型,无需明确指定变量类型,赋值的同时会自动声明类型. x = 1 y = 2.0 nam ...

  7. DB天气app冲刺第十一天

    今天是第十一天了.今天遇到了一个很麻烦的问题 就是程序好好的然后调试运行之后能够安装成功 但总是运行不了 一直闪退.最主要的问题是代码还没有问题,这是最让人揪心的一个问题了.因为有bug的话还可以改, ...

  8. 实时数据处理环境搭建flume+kafka+storm:1.zookeeper 安装配置

    1. 解压 tar -zxvf 2.创建目录  zk根目录创建         mkdir zkdatalog  --日志          mkdir zkdata  ---快照文件 3.修改配置文 ...

  9. 3.5 spring-replaced-method 子元素的使用与解析

    1.replaced-method 子元素 方法替换: 可以在运行时用新的方法替换现有的方法,与之前的 look-up不同的是replace-method 不但可以动态地替换返回的实体bean,而且可 ...

  10. 弹窗开关js

    // var guanbi = false; // $("#testbtn").click(function(){ // if(guanbi){ // $("#tan&q ...