对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画。

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

作者:Jeff 发表于:2007年12月21日 11:27 最后更新于: 2007年12月21日 12:38

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明。

http://www.blogjava.net/jeff-lau/archive/2007/12/21/169257.html

笔画排序

要按笔画排序,就要实现笔画比较器。

class StokeComparator implements Comparator

如果有个方法可以求得汉字的笔画数,上面的功能就很容易实现。如何求一个汉字的笔画数?最容易想到的就是查表法。建一个汉字笔画数表,如:

汉字

Unicode编码

笔画数

U4E00

1

U4E8C

2

U9F8D

16

...

...

...

表二

如果是连续的、按unicode编码排好顺序的表,实际存储在笔画数表中的只需最后一列就够了。

那如何建这个表呢?这个表存储在哪里?

建汉字笔画数表

现在大多数系统还只能支持Unicode中的基本汉字那部分汉字,编码从U9FA6-U9FBF。所以我们只建这部分汉字的笔画表。汉字笔画数表,我们可以按照下面的方法生成:

用java程序生成一个文本文件(Chinese.csv)。包括所有的从U9FA6-U9FBF的字符的编码和文字。利用excel的按笔画排序功能,对Chinese.csv文件中的内容排序。

编写Java程序分析Chinese.csv文件,求得笔画数, 生成ChineseStroke.csv。矫正笔画数,重新按汉字的Unicode编码对ChineseStroke.csv文件排序。

只保留ChineseStroke.csv文件的最后一列,生成Stroke.csv。

生成Chinese.csv的Java程序

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility.preface;7

8 import java.io.IOException;9 import java.io.PrintWriter;10

11 public classChineseCoder {12

13 public static voidmain(String[] args) throws IOException {14 PrintWriter out = new PrintWriter("Chinese.csv");15 //基本汉字

16 for (char c = 0x4E00; c <= 0x9FA5; c++) {17 out.println((int) c + "," +c);18 }19 out.flush();20 out.close();21

22 }23

24 }

初始化笔画数

从Excel排序过后的Chinese.csv文件来看,排好序的文件还是有一定规律的。在文件的第9行-12行可以看出:逐行扫描的时候,当unicode会变小了,笔画数也就加1。

20059,乛

20101,亅

19969,丁

19970,丂

用下面的Java程序分析吧。

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility.preface;7

8 import java.io.File;9 import java.io.IOException;10 import java.io.PrintWriter;11 import java.util.Scanner;12

13 public classStroke {14

15 /**16 * @param args17 * @throws IOException18 */

19 public static voidmain(String[] args) throws IOException {20 Scanner in = new Scanner(new File("Chinese.csv"));21 PrintWriter out = new PrintWriter("ChineseStroke.csv");22 String oldLine = "999999";23 int stroke = 0;24 while (in.hasNextLine()) {25 String line = in.nextLine();26 if (line.compareTo(oldLine) < 0) {27 stroke++;28 }29 oldLine =line;30 out.println(line + "," +stroke);31 }32 out.flush();33 out.close();34 in.close();35 }36

37 }

上面用的这个规律有问题吗?有问题,从ChineseStroke.csv文件抽取最后几个汉字就发现,笔画数不对。为什么呢?

笔画数可能不是连续的。

n+1笔画数的最小Unicode码可能比n笔画数的最大Unicode码要大

我们要人工核对ChineseStroke文件,但只要核对在笔画变化的那几个汉字的笔画数。最后,我发现,只有笔画数多于30的少数几个汉字的笔画数不对。核对并矫正笔画数后,用Excel按Unicode重新排序,去掉汉字和Unicode两列,只保留笔画数那列,得到Stroke.csv文件。

求得笔画数的方法和笔画比较器方法

求得笔画数的方法测试代码:

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility.test;7

8 import staticorg.junit.Assert.assertEquals;9

10 import org.junit.Before;11 import org.junit.Test;12 import chinese.utility.Chinese;13

14 public classStrokeTest {15

16 Chinese chinese;17

18 @Before19 public voidsetUp() {20 chinese = newChinese();21 }22

23 @Test24 public voidtestStroke() {25 assertEquals(1, chinese.stroke('一'));26 }27

28 @Test29 public voidtestStroke2() {30 assertEquals(2, chinese.stroke('二'));31 }32

33 @Test34 public voidtestStroke16() {35 assertEquals(16, chinese.stroke('龍'));36 }37

38 @Test39 public voidtestStrokeABC() {40 assertEquals(-1, chinese.stroke('a'));41 }42

43 }

求得笔画数的方法代码

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility;7

8 import java.util.Comparator;9

10 public class StrokeComparator implements Comparator{11

12 public intcompare(String o1, String o2) {13

14 Chinese chinese = newChinese();15

16 for (int i = 0; i < o1.length() && i < o2.length(); i++) {17 int codePoint1 =o1.codePointAt(i);18 int codePoint2 =o2.codePointAt(i);19 if (codePoint1 ==codePoint2)20 continue;21

22 int stroke1 =chinese.stroke(codePoint1);23 int stroke2 =chinese.stroke(codePoint2);24

25 if (stroke1 < 0 || stroke2 < 0) {26 return codePoint1 -codePoint2;27 }28

29 if (stroke1 !=stroke2) {30 return stroke1 -stroke2;31 }32 }33

34 return o1.length() -o2.length();35 }36 }

笔画比较器测试

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility.test;7

8 import java.util.Comparator;9

10 import org.junit.Assert;11 import org.junit.Before;12 import org.junit.Test;13

14 import chinese.utility.StrokeComparator;15

16 public classStrokeComparatorTest {17

18 private Comparatorcomparator;19

20 @Before21 public voidsetUp() {22 comparator = newStrokeComparator();23 }24

25 /**26 * 相同笔画数27 */

28 @Test29 public voidtestCompareEquals() {30 Assert.assertTrue(comparator.compare("一", "丨") == 0);31 }32

33 /**34 * 不同笔画数35 */

36 @Test37 public voidtestCompare() {38 Assert.assertTrue(comparator.compare("一", "二") < 0);39 Assert.assertTrue(comparator.compare("唔", "马") > 0);40 }41

42 /**43 * 长度不同44 */

45 @Test46 public voidtestCompareDefficultLength() {47 Assert.assertTrue(comparator.compare("二", "二一") < 0);48 }49

50 /**51 * 非汉字的比较52 */

53 @Test54 public voidtestABC() {55 Assert.assertTrue(comparator.compare("一", "a") > 0);56 Assert.assertTrue(comparator.compare("a", "b") < 0);57 }58 }

笔画比较器

1 /**2 * @author Jeff3 *4 * Copyright (c) 复制或转载本文,请保留该注释。5 */

6 package chinese.utility.test;7

8 import java.util.Comparator;9

10 import org.junit.Assert;11 import org.junit.Before;12 import org.junit.Test;13

14 import chinese.utility.StrokeComparator;15

16 public classStrokeComparatorTest {17

18 private Comparatorcomparator;19

20 @Before21 public voidsetUp() {22 comparator = newStrokeComparator();23 }24

25 /**26 * 相同笔画数27 */

28 @Test29 public voidtestCompareEquals() {30 Assert.assertTrue(comparator.compare("一", "丨") == 0);31 }32

33 /**34 * 不同笔画数35 */

36 @Test37 public voidtestCompare() {38 Assert.assertTrue(comparator.compare("一", "二") < 0);39 Assert.assertTrue(comparator.compare("唔", "马") > 0);40 }41

42 /**43 * 长度不同44 */

45 @Test46 public voidtestCompareDefficultLength() {47 Assert.assertTrue(comparator.compare("二", "二一") < 0);48 }49

50 /**51 * 非汉字的比较52 */

53 @Test54 public voidtestABC() {55 Assert.assertTrue(comparator.compare("一", "a") > 0);56 Assert.assertTrue(comparator.compare("a", "b") < 0);57 }58 }

其他程序的汉字排序

Microsoft在这方面做得比较好。如Sql server 2000,Word和Excel都能按拼音和笔画排序。而Oracle只能是采取宽松拼音排序法。

java 笔画排序_Java汉字排序(3)按笔划排序相关推荐

  1. java 汉字拼音排序_Java汉字排序(2)按拼音排序

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

  2. java list多字段排序_java中list通过多条件排序

    实现的效果类似于这样,首先通过一级类别id排序,其次是二级类别,最后是二级类别中的各项合计排序: 方法一 /** * 单品容器排序 * * @param productSellStatList * @ ...

  3. java 汉字按拼音排序_Java汉字按照拼音排序

    @Test public void testSortPinyin() { Collator cmp = Collator.getInstance(java.util.Locale.CHINA); St ...

  4. java list 多条件排序_java – 如何对arraylist执行一系列排序操作(多个排序条件)

    Collections.sort(myList,new Comparator() { @Override public int compare(Object o1,Object o2) { // wr ...

  5. java数组随机排序_JAVA 生成随机数数组,并排序输出

    package com.koal.test; import java.util.Arrays; /** * * @author hp * 排序 */ public class Sort { //要生成 ...

  6. java如何对list进行排序_java中如何对list进行排序

    java类中用Collections的sort方法对一个list进行排序,比较简单 先建一个User对象 public class User { public String name; public ...

  7. java字符串字典排序_java实现对map的字典序排序操作示例

    本文实例讲述了java实现对map的字典序排序操作.分享给大家供大家参考,具体如下: java中对map的字典序排序,算法验证比对微信官网https://mp.weixin.qq.com/wiki?t ...

  8. java对类数组进行排序_Java比较器类对数组进行排序

    小编典典 [-]应该如何声明Java Comparator类以按其降序将数组的第一个元素排序 [-] 这是使用Java 8的完整示例: import java.util.*; public class ...

  9. java重排序_Java synchronized 能防止指令重排序吗?

    @ZealTalk 说的是 synchronized 可以防止指令重排,这个观点不对的,也欢迎回答的各位来讨论 synchronized 的有序性 来讨论这个问题先,先看看 Java 里的操作无序现象 ...

  10. java首字母排序_Java实现按中文首字母排序的具体实例

    这篇文章主要介绍了Java实现按中文首字母排序的具体实例,有需要的朋友可以参考一下 要实现"按中文首字母排序"操作,可以使用java.util包下的Arrays类的sort()函数 ...

最新文章

  1. 《应用时间序列分析:R软件陪同》——1.5 习题
  2. 离职半年了,最近又开始被吐槽输出不够...
  3. 60秒计时器的仿真电路_物联网应用基于Arm微控制器的低功耗定时关机计时器
  4. SAP 质检使用非物料基本单位
  5. RedHat Enterprise Linux之raid5磁盘阵列
  6. mysql 5.7 super_MySQL 5.7 下的对super用户只读
  7. java会被rust替代吗_自从尝了 Rust,Java 突然不香了
  8. 第6课 细胞分裂 《小学生C++趣味编程》--C++、Scratch
  9. ngx.location.capture 只支持相对路径,不能用绝对路径
  10. c语言用switch做一个计算器,求助。。关于用switch编写简易计算器
  11. ubuntu16中,google浏览器安装OneNote Web Clipper插件
  12. Java画十字_用Java绘制对角线
  13. linux下如何查看tlq服务,谁能跟我讲解一下bashrc?
  14. 高德地图获取经纬度并逆定位获取地理位置名称(原生)
  15. java 真少林倚天屠龙夺艳记,2019年9月13日資訊重點:月夜吟詠詩意長安十九屆中央第四輪巡視全部進駐...
  16. 【趣读官方文档】1.管家的抉择 (Android进程生命周期)
  17. 长安沦陷国家破碎,只有山河依旧,
  18. C语言基础教程 之 如何定义变量!
  19. 怀旧服美服哪个服务器人最多,暴雪:魔兽世界经典怀旧服美服排队人数恐破万...
  20. ERP销售管理实施的意义

热门文章

  1. 详解Unity中的生命周期函数
  2. 计算机提示无法识别优盘,U盘插入电脑提示无法识别的解决方法
  3. 服务器编程之路:进无止境(下)
  4. python12306抢票_Python 12306 的抢票工具
  5. UVA1589 象棋 Xiangqi
  6. Barsetto百胜图美式便携咖啡机测评只为一杯好咖啡
  7. 2019年京东面试题-洗咖啡杯问题【贪心和动态规划】
  8. NYOJ-108-士兵杀敌(一)
  9. phyton做彩色电子管
  10. android iCloud 短信,云助手 基于安卓的iCloud