- 浏览: 467408 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ty1972873004:
sunwang810812 写道我运行了这个例子,怎么结果是这 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
lgh1992314:
simpleDean 写道请问,Logger.setLevel ...
Java内置Logger详解 -
sunwang810812:
我运行了这个例子,怎么结果是这样的:2号车泊车6号车泊车5号车 ...
Java并发编程: 使用Semaphore限制资源并发访问的线程数 -
jp260715007:
nanjiwubing123 写道参考你的用法,用如下方式实现 ...
面试题--三个线程循环打印ABC10次的几种解决方法 -
cb_0312:
SurnameDictionary文章我没看完,现在懂了
中文排序
对于一个数组或者列表或者集合的元素进行排序是一个比较常用的需求。现有的Java类库也提供了API来实现这样的功能,比如Arrays.sort以及Collections.sort的方法。另外,我们也可以用Collator来实现中文的排序。
package demo; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; public class TestCollator { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("中"); list.add("文"); list.add("拼"); list.add("音"); list.add("鑫"); list.add("犇"); Collections.sort(list, Collator.getInstance(Locale.CHINA)); for(String ele: list) { System.out.println(ele); } } }
输出的结果是:
拼
文
音
中
鑫
犇
中文排序后的结果,并不完全正确。
这是因为Java使用的是Unicode编码,而常用的中文编码是GB2312,它包含了7000个字符集而且是按照拼音排序的,也是连续的。GB18030和GBK都是在此基础上扩展起来的,这样就会造成Unicode的不连续性,最终导致对有些中文字符排序不完全正确的结果。
为了能够更好地对中文进行排序,我们可以采用拼音或者笔画来对中文进行排序。本文采用了拼音来排序。将汉语转换成拼音的开源项目有PinYin4j,下载的地址如下:
http://sourceforge.net/projects/pinyin4j/files/pinyin4j-2.5.0/pinyin4j-2.5.0/pinyin4j-2.5.0.zip/download
编写汉字转换成拼音的工具类
package demo; import java.io.UnsupportedEncodingException; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; public final class PinYinUtils { private PinYinUtils() { } /** * 判断一个字符是否是中文字符 */ private static boolean isChineseCharacter(char c) { return String.valueOf(c).matches("[\\u4E00-\\u9FA5]+"); } /** * 将一个含有中文的字符串转换成拼音。 * Note: 这里只是将中文转换成拼音,其它的各种字符将保持原来的样子。 */ public static String populatePinYing(String aChineseValue) { if (null == aChineseValue) { return null; } StringBuilder sb = new StringBuilder(); char[] charArray = aChineseValue.toCharArray(); HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat(); outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); outputFormat.setVCharType(HanyuPinyinVCharType.WITH_V); outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); for (int i = 0; i < charArray.length; i++) { if (isChineseCharacter(charArray[i])) { try { sb.append(PinyinHelper.toHanyuPinyinStringArray( charArray[i], outputFormat)[0]); } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { sb.append(charArray[i]); } } return sb.toString(); } /** * 将一个含有中文的字符串转换成拼音。 * Note: 这里只是将中文转换成拼音,其它的各种字符将保持原来的样子。 * * 在這裡多了一個參數needToCorrectSpelling,这个主要用于调整姓氏的发音。 * 如 '单', 这个字作为姓氏念 shan, 但同时也有dan的发音等。 * * 为了保证姓氏发音的正确性,将了这个参数和相关的简单逻辑 */ public static String populatePinYing(String aChineseValue, boolean needToCorrectSpelling) { if (null == aChineseValue) { return null; } StringBuilder sb = new StringBuilder(); char[] charArray = aChineseValue.toCharArray(); HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat(); outputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); outputFormat.setVCharType(HanyuPinyinVCharType.WITH_V); String surname = null; for (int i = 0; i < charArray.length; i++) { if (isChineseCharacter(charArray[i])) { try { if (needToCorrectSpelling && 0 == i) { surname = SurnameDictionary .populateCorrectSpelling(charArray[i]); if (null == surname) { sb.append(PinyinHelper.toHanyuPinyinStringArray( charArray[i], outputFormat)[0]); } else { sb.append(surname); } } else { sb.append(PinyinHelper.toHanyuPinyinStringArray( charArray[i], outputFormat)[0]); } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } } else { sb.append(charArray[i]); } } return sb.toString(); } public static void main(String[] args) throws UnsupportedEncodingException { String x = "拼音4j%^**Cool12568 カ キ "; System.out.println(populatePinYing(x)); } }
本文的一个简单例子是对名字进行排序,所以下面创建两个类 User 和 NameComparator
package demo; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = -1221268239932915488L; private String name; private int age; /** * @param name * @param age */ public User(String name, int age) { this.name = name; this.age = age; } public User() { } /** * @return the name */ public String getName() { return name; } /** * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * @return the age */ public int getAge() { return age; } /** * @param age * the age to set */ public void setAge(int age) { this.age = age; } }
package demo; import java.util.Comparator; public class NameComparator implements Comparator<User> { public int compare(User u1, User u2) { String name1 = u1.getName(); String name2 = u2.getName(); return PinYinUtils.populatePinYing(name1).compareTo( PinYinUtils.populatePinYing(name2)); } }
测试代码如下:
package demo; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Test { public static void main(String[] args) { run(); } private static void run() { List<User> list = prepareTestUserList(); printListBeforeSorting(list); Collections.sort(list, new NameComparator()); printListAfteSorting(list); } private static void printListAfteSorting(List<User> list) { System.out.println("After sorting....."); printList(list); } private static void printListBeforeSorting(List<User> list) { System.out.println("Before sorting....."); printList(list); } private static void printList(List<User> list) { for (User user : list) { System.out.println(user.getName()); } } private static List<User> prepareTestUserList() { List<User> list = new ArrayList<User>(); User u = new User(); u.setName("张三"); u.setAge(21); list.add(u); u = new User(); u.setName("李四"); u.setAge(18); list.add(u); u = new User(); u.setName("王五"); u.setAge(25); list.add(u); u = new User(); u.setName("鑫鑫"); u.setAge(89); list.add(u); u = new User(); u.setName("范范"); u.setAge(89); list.add(u); u = new User(); u.setName("单一号"); u.setAge(89); list.add(u); u = new User(); u.setName("犇犇"); u.setAge(89); list.add(u); return list; } }
Before sorting.....
张三
李四
王五
鑫鑫
范范
单一号
犇犇
After sorting.....
犇犇
单一号
范范
李四
王五
鑫鑫
张三
从上述的排序结果,可以看出“单一号”并没有在一个准确的位置上。产生这种情况是因为中文存在多音字,而且姓氏中的发音会不一样。如“单”在姓氏中需要发“shan”,用PinYin4j能够返回多音字,因为不知道哪一个正确,我在代码中返回了第一个 “dan”。
为了能够保证姓氏发声的正确性,个人想到的有三种:1. 数据库中存储姓氏发音的表
2. 将姓氏的发音存储在一个key-value的properties文件中
3. 创建一个姓氏发音的字典类
本文简单采用第三种方式来实现:
package demo; public class SurnameDictionary { public static String populateCorrectSpelling(char surname) { //TODO: if ('单' == surname) { return "shan"; } return null; } }
比较器中加入参数,将SurnameDictionary运用上去。
package demo; import java.util.Comparator; public class NameComparator implements Comparator<User> { public int compare(User u1, User u2) { String name1 = u1.getName(); String name2 = u2.getName(); return PinYinUtils.populatePinYing(name1, true).compareTo( PinYinUtils.populatePinYing(name2, true)); } }
重新运行结果,我们将得到正确的名字排序结果:
Before sorting.....
张三
李四
王五
鑫鑫
范范
单一号
犇犇
After sorting.....
犇犇
范范
李四
单一号
王五
鑫鑫
张三
评论
4 楼
cb_0312
2016-06-22
SurnameDictionary文章我没看完,现在懂了
3 楼
cb_0312
2016-06-22
SurnameDictionary.populateCorrectSpelling(charArray[i])
这个类是什么?我怎么找不到相关信息?
这个类是什么?我怎么找不到相关信息?
2 楼
MouseLearnJava
2013-07-17
oaklet 写道
只能做到这一步了,再向下没法做了,毕竟有些怪字音不确定,非人力所能为,例如
常见的姓氏用字异读有:
重:Chóng 音崇;
区:ōu 音欧;
仇:Qiú 音求;
秘:Bì 音闭;
冼:Xiǎn 音显;
解:Xiè 音谢;
折:Shè 音舌;
单:Shàn 音善;
朴:Piáo 音瓢;
翟:Zhá 音宅;
查:Zhā 音渣;
万俟:Mò qí 音莫奇;
尉迟:Yù chí 音玉迟;等等。
还有一些姓氏用字,一字两音,同一个作为姓氏的汉字,由于有两个读音,就代表了两个不同的姓,而且不一源流。如:“乐”姓,北方读音与“月”字同,而南方读音则与“勒”字同音;“召”姓,汉族人读者作“少”,而傣族人则读作“赵”;原籍在中原一带的“罩”姓,读音作“谈”,而注籍两广或壮族的则读音与“秦”字同。这些同字不同音者,分别表示不同的姓,不能认为是同一姓氏在不同地区、不同族属的不同读法。
常见的姓氏用字异读有:
重:Chóng 音崇;
区:ōu 音欧;
仇:Qiú 音求;
秘:Bì 音闭;
冼:Xiǎn 音显;
解:Xiè 音谢;
折:Shè 音舌;
单:Shàn 音善;
朴:Piáo 音瓢;
翟:Zhá 音宅;
查:Zhā 音渣;
万俟:Mò qí 音莫奇;
尉迟:Yù chí 音玉迟;等等。
还有一些姓氏用字,一字两音,同一个作为姓氏的汉字,由于有两个读音,就代表了两个不同的姓,而且不一源流。如:“乐”姓,北方读音与“月”字同,而南方读音则与“勒”字同音;“召”姓,汉族人读者作“少”,而傣族人则读作“赵”;原籍在中原一带的“罩”姓,读音作“谈”,而注籍两广或壮族的则读音与“秦”字同。这些同字不同音者,分别表示不同的姓,不能认为是同一姓氏在不同地区、不同族属的不同读法。
非常感谢你的评论。 姓氏用字异读方面,个人觉得能够通过建立一个发音词典库等方式加以改进。像姓氏一字多读的情况,发什么音不确定性太大,不好做。
在中文排序(如名字)上,尽可能考虑到姓氏异读的情况,对姓氏一字多音的情况保持一颗宽容的心吧。
其他博友有好的建议或意见,也请一起分享吧
1 楼
oaklet
2013-07-16
只能做到这一步了,再向下没法做了,毕竟有些怪字音不确定,非人力所能为,例如
常见的姓氏用字异读有:
重:Chóng 音崇;
区:ōu 音欧;
仇:Qiú 音求;
秘:Bì 音闭;
冼:Xiǎn 音显;
解:Xiè 音谢;
折:Shè 音舌;
单:Shàn 音善;
朴:Piáo 音瓢;
翟:Zhá 音宅;
查:Zhā 音渣;
万俟:Mò qí 音莫奇;
尉迟:Yù chí 音玉迟;等等。
还有一些姓氏用字,一字两音,同一个作为姓氏的汉字,由于有两个读音,就代表了两个不同的姓,而且不一源流。如:“乐”姓,北方读音与“月”字同,而南方读音则与“勒”字同音;“召”姓,汉族人读者作“少”,而傣族人则读作“赵”;原籍在中原一带的“罩”姓,读音作“谈”,而注籍两广或壮族的则读音与“秦”字同。这些同字不同音者,分别表示不同的姓,不能认为是同一姓氏在不同地区、不同族属的不同读法。
常见的姓氏用字异读有:
重:Chóng 音崇;
区:ōu 音欧;
仇:Qiú 音求;
秘:Bì 音闭;
冼:Xiǎn 音显;
解:Xiè 音谢;
折:Shè 音舌;
单:Shàn 音善;
朴:Piáo 音瓢;
翟:Zhá 音宅;
查:Zhā 音渣;
万俟:Mò qí 音莫奇;
尉迟:Yù chí 音玉迟;等等。
还有一些姓氏用字,一字两音,同一个作为姓氏的汉字,由于有两个读音,就代表了两个不同的姓,而且不一源流。如:“乐”姓,北方读音与“月”字同,而南方读音则与“勒”字同音;“召”姓,汉族人读者作“少”,而傣族人则读作“赵”;原籍在中原一带的“罩”姓,读音作“谈”,而注籍两广或壮族的则读音与“秦”字同。这些同字不同音者,分别表示不同的姓,不能认为是同一姓氏在不同地区、不同族属的不同读法。
发表评论
-
工厂类中移除if/else语句
2016-07-10 19:52 910面向对象语言的一个强大的特性是多态,它可以用来在代码中移除 ... -
Java编程练手100题
2014-12-11 17:13 6735本文给出100道Java编程练手的程序。 列表如下: 面 ... -
数组复制的三种方法
2014-11-30 12:57 2224本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
数组复制的三种方法
2014-11-30 12:54 0本文将给出三种实现数组复制的方法 (以复制整数数组为例)。 ... -
四种复制文件的方法
2014-11-29 13:21 1746尽管Java提供了一个类ava.io.File用于文件的操 ... -
判断一个字符串中的字符是否都只出现一次
2014-11-25 12:58 2734本篇博文将给大家带来几个判断一个字符串中的字符是否都只出现一 ... -
使用正则表达式判断一个数是否为素数
2014-11-23 13:35 2175正则表达式能够用于判断一个数是否为素数,这个以前完全没有想过 ... -
几个可以用英文单词表达的正则表达式
2014-11-21 13:12 3759本文,我们将来看一下几个可以用英文单词表达的正则表达式。这些 ... -
(广度优先搜索)打印所有可能的括号组合
2014-11-20 11:58 1961问题:给定一个正整n,作为括号的对数,输出所有括号可能 ... -
随机产生由特殊字符,大小写字母以及数字组成的字符串,且每种字符都至少出现一次
2014-11-19 14:48 3984题目:随机产生字符串,字符串中的字符只能由特殊字符 (! ... -
找出1到n缺失的一个数
2014-11-18 12:57 3185题目:Problem description: You h ... -
EnumSet的几个例子
2014-11-14 16:24 8759EnumSet 是一个与枚举类型一起使用的专用 Set 实现 ... -
给定两个有序数组和一个指定的sum值,从两个数组中各找一个数使得这两个数的和与指定的sum值相差最小
2014-11-12 11:24 3336题目:给定两个有序数组和一个指定的sum值,从两个数组 ... -
Java面试编程题练手
2014-11-04 22:49 6707面试编程 写一个程序,去除有序数组中的重复数字 编 ... -
Collections用法整理
2014-10-22 20:55 9851Collections (java.util.Collect ... -
The Code Sample 代码实例 个人博客开通
2014-09-04 18:48 1424个人博客小站开通 http://thecodesample. ... -
Collections.emptyXXX方法
2014-06-08 13:37 2148从JDK 1.5开始, Collections集合工具类中预先 ... -
这代码怎么就打印出"hello world"了呢?
2014-06-08 00:37 7401for (long l = 4946144450195624L ... -
最短时间过桥
2014-04-21 22:03 4163本文用代码实现最短时间过桥,并且打印如下两个例子的最小过桥时间 ... -
将数组分割成差值最小的子集
2014-04-20 22:34 2907本文使用位掩码实现一个功能 ==》将数组分割成差值最小的子集 ...
相关推荐
在Microsoft Foundation Classes (MFC)库中,进行汉字排序是一个常见的需求,特别是在处理中文数据时。MFC提供了丰富的类和函数来支持C++编程,它为Windows应用程序开发提供了一种结构化的方式。在这个主题中,我们...
在SQLiteDatabase,特别是SQLite3中,处理中文排序问题是一个常见的挑战。SQLite3是一个轻量级、自包含的数据库引擎,广泛应用于嵌入式系统和移动应用。然而,它默认的排序规则可能不适用于中文字符,因为中文字符的...
默认情况下,Java使用自然排序,即按照字符串的Unicode值进行排序,这对于英文字符和数字来说通常是合适的,但对于中文字符则不是我们期望的排序方式。 为了实现中文、数字和字母的排序,我们需要创建一个`...
本文将详细介绍如何解决EasyUI Datagrid中的中文排序问题,并分别从前端和后端两个角度给出具体的实现方案。 #### 二、EasyUI Datagrid简介 EasyUI 是一个基于 jQuery 的简单而强大的 UI 库,它提供了大量的用户...
### 数字字母中文排序知识点详解 #### 一、概述 在处理包含数字、字母与中文字符的数据时,正确的排序逻辑尤为重要。本篇文章将基于提供的代码片段来深入探讨如何实现一个能够处理这三种类型字符的排序算法,并且...
在处理数据库中的中文数据时,我们常常会遇到中文排序的问题。默认情况下,SQL的排序机制可能会导致中文字符按照其内部编码(通常是Unicode编码)进行排序,这与我们的预期(比如按照拼音或笔画顺序)可能不一致。...
然而,默认情况下,ExtJS的数据排序功能主要基于英文字符集,当遇到中文数据时,排序结果可能不符合预期。 #### 问题分析 中文排序的核心在于正确处理中文字符的比较。由于中文字符的Unicode编码并非按照汉语拼音或...
小程序案例视频,汉字排序
在本文中,我们将深入探讨如何使用Qt5框架在VS2015开发环境中实现中文和英文的排序功能。Qt5提供了QCollator和QLocale库,使得开发者能够方便地处理各种语言的排序需求,包括中文的拼音排序和笔画排序。 首先,...
在iOS开发中,当涉及到中文数据的排序时,由于中文字符的复杂性,不能像英文那样简单地按照字典顺序进行排序。此时,我们需要引入特定的算法和库来处理中文字符的拼音转换,以便实现正确的排序。这篇内容将详细介绍...
### Oracle数据库中汉字排序方法 在Oracle数据库中处理中文数据时,经常需要对包含中文字符的数据表...通过以上内容的学习与实践,我们可以有效地在Oracle数据库中实现汉字排序功能,从而更好地管理和利用中文数据。
EXTJS Grid默认的排序机制对于英文字符处理得较好,但对于中文字符,由于编码和比较规则的不同,可能会导致排序结果不正确。本教程将详细讲解如何修正EXTJS Grid中的中文排序问题。 首先,我们需要理解EXTJS Grid的...
本文将深入探讨如何解决这些问题,确保MySQL数据库中的中文数据能按照正确的顺序进行排序。 首先,我们需要了解MySQL字符集的基础知识。MySQL支持多种字符集,如GBK、UTF-8等,它们用于存储和表示不同语言的字符。...
Swift本身提供的排序功能对于英文字符集是足够的,但当涉及到中文字符时,由于Unicode编码的复杂性,直接使用默认的排序方法可能无法得到预期的结果。中文字符的排序需要考虑到汉字的拼音、笔画或者字典顺序。...
在线中英文根据首字母排序工具: http://tools.jb51.net/aideddesign/zh_paixu 您可能感兴趣的文章:mysql的中文数据按拼音排序的2个方法mysql如何按照中文排序解决方案MySQL按照汉字的拼音排序简单实例
在Java编程语言中,处理中文和英文混合的排序问题是一个常见的需求,特别是在处理用户输入、数据库数据或文件名等场景。这个"关于中文英文混合排序javaDemo"的示例主要展示了如何实现这样的功能。让我们深入探讨一下...
中文排序与英文或其他语言排序的主要区别在于,中文字符通常按照拼音顺序而非字母顺序进行排列。因此,直接使用JavaScript内置的`localeCompare`函数可能无法达到预期的效果。此外,还需要考虑到中文字符的特殊性...
在中文环境中,我们通常希望按照汉字的拼音或笔画顺序来排序。 为了解决这个问题,我们可以重写Ext.data.Store的`applySort`函数,以便在进行本地排序时应用中文排序规则。上述代码正是这样一个解决方案。它将原生...
在JavaScript中,中文排序是一个常见的需求,特别是在处理包含中文数据的数组时。`sort()`函数是JavaScript中的一个内置方法,用于对数组进行原地排序。然而,它默认的排序方式是基于Unicode编码,这并不适合中文...