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

本文就讲述如何实现按笔划排序的比较器(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<String>

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

汉字 Unicode编码 笔画数
U4E00 1
U4E8C 2
U9F8D 16
... ... ...

表二

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

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

建汉字笔画数表

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

  1. 用java程序生成一个文本文件(Chinese.csv)。包括所有的从U9FA6-U9FBF的字符的编码和文字。利用excel的按笔画排序功能,对Chinese.csv文件中的内容排序。
  2. 编写Java程序分析Chinese.csv文件,求得笔画数, 生成ChineseStroke.csv。矫正笔画数,重新按汉字的Unicode编码对ChineseStroke.csv文件排序。
  3. 只保留ChineseStroke.csv文件的最后一列,生成Stroke.csv。

在这里 下载上面3个步骤生成的3个文件。

生成Chinese.csv的Java程序

 1 /**
 2  * @author Jeff
 3  *
 4  * Copyright (c) 复制或转载本文,请保留该注释。
 5  */
 6 package chinese.utility.preface;
 7
 8 import java.io.IOException;
 9 import java.io.PrintWriter;
10
11 public class ChineseCoder {
12
13     public static void main(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 Jeff
 3  *
 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 class Stroke {
14
15     /**
16      * @param args
17      * @throws IOException
18      */
19     public static void main(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 Jeff
 3  *
 4  * Copyright (c) 复制或转载本文,请保留该注释。
 5  */
 6 package chinese.utility.test;
 7
 8 import static org.junit.Assert.assertEquals;
 9
10 import org.junit.Before;
11 import org.junit.Test;
12 import chinese.utility.Chinese;
13
14 public class StrokeTest {
15
16     Chinese chinese;
17
18     @Before
19     public void setUp() {
20         chinese = new Chinese();
21     }
22
23     @Test
24     public void testStroke() {
25         assertEquals(1, chinese.stroke('一'));
26     }
27
28     @Test
29     public void testStroke2() {
30         assertEquals(2, chinese.stroke('二'));
31     }
32
33     @Test
34     public void testStroke16() {
35         assertEquals(16, chinese.stroke('龍'));
36     }
37
38     @Test
39     public void testStrokeABC() {
40         assertEquals(-1, chinese.stroke('a'));
41     }
42
43 }

求得笔画数的方法代码

 1 /**
 2  * @author Jeff
 3  *
 4  * Copyright (c) 复制或转载本文,请保留该注释。
 5  */
 6 package chinese.utility;
 7
 8 import java.util.Comparator;
 9
10 public class StrokeComparator implements Comparator<String> {
11
12     public int compare(String o1, String o2) {
13
14         Chinese chinese = new Chinese();
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 Jeff
 3  *
 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 class StrokeComparatorTest {
17
18     private Comparator<String> comparator;
19
20     @Before
21     public void setUp() {
22         comparator = new StrokeComparator();
23     }
24
25     /**
26      * 相同笔画数
27      */
28     @Test
29     public void testCompareEquals() {
30         Assert.assertTrue(comparator.compare("一", "丨") == 0);
31     }
32
33     /**
34      * 不同笔画数
35      */
36     @Test
37     public void testCompare() {
38         Assert.assertTrue(comparator.compare("一", "二") < 0);
39         Assert.assertTrue(comparator.compare("唔", "马") > 0);
40     }
41
42     /**
43      * 长度不同
44      */
45     @Test
46     public void testCompareDefficultLength() {
47         Assert.assertTrue(comparator.compare("二", "二一") < 0);
48     }
49
50     /**
51      * 非汉字的比较
52      */
53     @Test
54     public void testABC() {
55         Assert.assertTrue(comparator.compare("一", "a") > 0);
56         Assert.assertTrue(comparator.compare("a", "b") < 0);
57     }
58 }

笔画比较器

 1 /**
 2  * @author Jeff
 3  *
 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 class StrokeComparatorTest {
17
18     private Comparator<String> comparator;
19
20     @Before
21     public void setUp() {
22         comparator = new StrokeComparator();
23     }
24
25     /**
26      * 相同笔画数
27      */
28     @Test
29     public void testCompareEquals() {
30         Assert.assertTrue(comparator.compare("一", "丨") == 0);
31     }
32
33     /**
34      * 不同笔画数
35      */
36     @Test
37     public void testCompare() {
38         Assert.assertTrue(comparator.compare("一", "二") < 0);
39         Assert.assertTrue(comparator.compare("唔", "马") > 0);
40     }
41
42     /**
43      * 长度不同
44      */
45     @Test
46     public void testCompareDefficultLength() {
47         Assert.assertTrue(comparator.compare("二", "二一") < 0);
48     }
49
50     /**
51      * 非汉字的比较
52      */
53     @Test
54     public void testABC() {
55         Assert.assertTrue(comparator.compare("一", "a") > 0);
56         Assert.assertTrue(comparator.compare("a", "b") < 0);
57     }
58 }

其他程序的汉字排序

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

转载于:https://www.cnblogs.com/sjjg/p/4930025.html

Java汉字排序(3)按笔划排序相关推荐

  1. Java汉字获取拼音、笔划、偏旁部首

    本文需要配合文本库使用,在文章底部附文本库文件 废话不多说 直接上代码: import java.io.BufferedReader; import java.io.IOException; impo ...

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

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

  3. 【我的Android进阶之旅】Android实现中文汉字笔划(笔画)排序、中文拼音排序、英文排序的国家地区选择界面

    一.需求描述 最近要做一个类似微信的,在登录界面选择国家地区的功能,微信有中文汉字笔画排序以及中文拼音排序等几种方式,如下所示: 微信:简体中文.拼音排序 微信:繁体中文.笔画排序 微信 英文 字母排 ...

  4. java字符串排序_对字符串排序持一种宽容的心态

    在Java中一涉及中文处理就会冒出很多问题来,其中排序也是一个让人头疼的课题,我们来看下面的代码: 上面的代码定义一个数组,然后进行升序排序,我们期望的结果是按照拼音升序排列,即为李四.王五.张三,但 ...

  5. 数字排在最前,英文字母其次,汉字则按照拼音进行排序,获取中文首字母

    中文名称,按照A-Z方式进行排序. import cn.hutool.extra.pinyin.PinyinUtil; import com.alibaba.nacos.client.utils.St ...

  6. java python算法_用Python,Java和C ++示例解释的排序算法

    java python算法 什么是排序算法? (What is a Sorting Algorithm?) Sorting algorithms are a set of instructions t ...

  7. java算法----排序----(6)希尔排序(最小增量排序)

    1 package log; 2 3 public class Test4 { 4 5 /** 6 * java算法---希尔排序(最小增量排序) 7 * 8 * @param args 9 */ 1 ...

  8. java 基础算法教程ppt,基础排序算法(附加java实现)

    七种最基本的排序算法:(面试必会!) 冒泡排序: 最基础的排序算法,从数列最前端开始,两两比较,如果前一个数比后一个数大,那么两个数就交换位置,经过一轮遍历之后,最大的数就到了数列的最后一个位置上,再 ...

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

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

最新文章

  1. nginx发布antd-pro项目(别人发的,未测试)
  2. 渗透新手福利---xss到获取cookie入门级
  3. Redis源码编译安装
  4. 非线性优化库liblbfgs初探
  5. 英语学习笔记2019-11-15
  6. 基于JAVA+SpringMVC+Mybatis+MYSQL的高校勤工助学管理系统
  7. 如何正确地使用#region指令
  8. JAVA在线小说电子书阅读系统毕业设计 开题报告
  9. linux 谷歌浏览器设置代理_Linux系统下Firefox浏览器SSH代理服务器脚本及设置方法...
  10. 《区块链革命》读书笔记1可信的协议 引导未来:区块链经济七大设计原则
  11. APP产品经理(一)
  12. Python基础 | 快速实现label_to_index
  13. Golang的一个简单实用的http客户端库httpc
  14. Error: Canceled future for execute_request message before replies were done
  15. npm i 安装时报错问题解决
  16. 常见功能测试设计方法
  17. vs2015 编译出错:Failed to register output......
  18. swf怎么和php实现交互,用ActionScript与JavaScript实现Flash与网页的交互
  19. [ZT稍长]毫不含糊地反对通货膨胀
  20. 【实战案例】表情分类人脸表情识别

热门文章

  1. mybatis resultMap之collection聚集两种实现方式
  2. Matlab 实现磁测数据日变改正
  3. Execution failed for task ‘:app:checkDebugAarMetadata‘.
  4. 项目引入svg格式图片无效
  5. 步步高vivo x5maxv手机刷机固件电信4G售后线刷包
  6. Xanadu宣布与格芯合作加速研发容错光量子计算机
  7. arcmap 线矢量批量提取多图层剖面线
  8. REPRINT CALLBACK
  9. 进击的短视频 异构计算驱动AI落地
  10. 微博、腾讯视频(部分)提取器-- 后台Node.js篇