- 浏览: 601909 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
Garlic_90:
ireport分页的话代码写起来有些复杂,我以前试过,比较简单 ...
ireport分页显示 -
feijiing:
nice,problem solved,thanks!
虚拟机安装centos no valid devices were found on which to cereate new file systems -
Jocken:
引用的jar包需要怎么加在命令里面?十多个呢,为什么配在MAN ...
linux 如何运行jar包 -
xiaoqiao800:
看到你的问题,有帮助,我之前都是手动的clear项目下的cla ...
The project cannot be built until build path errors are resolved -
mfkdzhou:
楼主好,我现在也遇到这个问题,可以把源代码发一份不?谢谢了。8 ...
java打印
Java中的中文排序问题(转载)
关键字: java实战
摘要:在Java中,对一个数组或列表(在本文中统称为集合)中的元素排序,是一个很经常的事情。好在Sun公司在Java库中实现了大部分功能。如果集合中的元素实现了Comparable接口,调用Array或Collections的静态(static)方法sort,就可以直接对集合排序。程序员用不同的方式实现了Comparator接口,就可以用各自不同的方式排序。对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画。本文就讲述如何实现这两种不同的比较器(Comparator)。
作者:Jeff 发表于:2007年12月21日 11:27 最后更新于: 2007年12月21日 12:38
版权声明:可以任意转载,转载时请务必以超链接形式标明文章 原始出处和作者信息及本版权声明。
[url]http://www.blogjava.net/jeff-lau/archive/2007/12/21/169257.html [/url]
排序概述
在Java中,对一个数组或列表(在本文中统称为集合)中的元素排序,是一个很经常的事情。好在Sun公司在Java库中实现了大部分功能。如果集合中的元素实现了Comparable接口,调用以下的静态(static)方法,就可以直接对集合排序。
Java代码
// 数组排序方法
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
java.util.Arrays.sort(type[] a);
// 数组排序方法
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
java.util.Arrays.sort(type[] a);
Java代码
// 列表
public static void sort(List list)
// 列表
public static void sort(List list)
以上的这些排序方式能满足大部分应用。但集合中的元素没有实现Comparable接口,或者集合中的元素要按一种特别的方式排序,这要怎么办?Sun公司早就想到了,并在Java库中提供上面两个方法的重载。
Java代码
// 数组排序方法。
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
public static void sort(T[] a, Comparator c)
// 数组排序方法。
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
public static void sort(T[] a, Comparator c)
Java代码
// 列表
public static void sort(List list, Comparator c)
// 列表
public static void sort(List list, Comparator c)
只要实现了Comparator接口,就可以按程序员自己的意思去排序了。对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画。汉字是通过一定的编码方式存储在计算机上的,主要的编码有:Unicdoe、GB2312和GBK等。
Unicode 编码中的汉字
Unicode中编码表分为两块,一个是基本的,一个是辅助的。现在的大多数操作系统还不支持Unicode中辅助区域中的文字,如WinXp。
在Java中的字符就是Unicode码表示的。对于Unicode基本区域中的文字,用两个字节的内存存储,用一个char表示,而辅助区域中的文字用 4个字节存储,因此辅助区域中的就要用两个char来表示了(表一种蓝色底就是辅助区域中的文字)。一个文字的unicode编码,在Java中统一用 codePoint(代码点)这个概念。
中文和日文、韩文一样是表意文字,在Unicode中,中日韩三国(东亚地区)的文字是统一编码的。CJK代表的就是中日韩。在这里,我把这3中文字,都作为汉字处理了。(日语和韩语可能就是从汉语中衍生的吧!)
汉字在Unicode中的分布大致如下表:
首字编码 尾字编码 个数
基本汉字 U4E00 U9FBF 20928
异性字 UF900 UFAFF 512
扩展A U3400 U4D8F 512
扩展B U20000 U2A6DF 42720
补充 U2F800 U2FA1F 544
其他 ...
表一
在这些编码区间,有些编码是保留的。
GB2312编码
GB2312是中华人民共和国最早的计算机汉字编码方式。大概有6000多个汉字,这些汉字是按拼音顺序编码的。这6000多个汉字都是简体中文字。
GBK编码
GB2312的扩展,并兼容GB2312。扩展后的汉字大概有2万多个,其中有简体汉字也有繁体汉字。
拼音排序
拼音有好几种方式,其中最主要的是中华人民共和国的汉语拼音 Chinese Phonetic。对汉字的排序有两种:一种是宽松的,能够按拼音排序最常用的汉字,另一种是严格的,能够按拼音排序绝大部分大部分汉字。
宽松的拼音排序法
原理:汉字最早是GB2312编码,收录了六千多个汉字,是按拼音排序的,编码是连续的。后来出现了GBK编码,对GB2312进行了扩展,到了两万多汉字,并且兼容GB2312,也就是说GB2312中的汉字编码是原封不动搬到GBK中的(在GBK编码中[B0-D7]区中)。
如果我们只关心这6000多个汉字的顺序,就可以用下面的方法实现汉字宽松排序。
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class PinyinSimpleComparator implements Comparator {
public int compare(String o1, String o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class PinyinSimpleComparator implements Comparator {
public int compare(String o1, String o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
}
}
在对[孙, 孟, 宋, 尹, 廖, 张, 徐, 昆, 曹, 曾,怡]这几个汉字排序,结果是:[曹, 昆, 廖, 孟, 宋, 孙, 徐, 尹, 曾, 张, 怡]。最后一个 怡 有问题,不该排在最后的。
注意:这个程序有两个不足
* 由于gb2312中的汉字编码是连续的,因此新增加的汉字不可能再按照拼音顺序插入到已有的gb2312编码中,所以新增加的汉字不是按拼音顺序排的。
* 同音字比较的结果不等于0 。
下面的测试代码可以证明
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") > 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") != 0);
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") > 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") != 0);
}
严格的拼音排序法
为了解决宽松的拼音的两点不足,可以通过实现汉语拼音的函数来解决。goolge下看到sf上有个pinyin4j的项目,可以解决这个问题,pinyin4j的项目地址是:http://pinyin4j.sourceforge.net/。
实现代码:
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper;
public class PinyinComparator implements Comparator {
public int compare(String o1, String o2) {
for (int i = 0; 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[0];
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper;
public class PinyinComparator implements Comparator {
public int compare(String o1, String o2) {
for (int i = 0; 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[0];
}
}
测试:
Java代码
/**
* @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 comparator = new PinyinComparator();
/**
* 常用字
*/
@Test
public void testCommon() {
Assert.assertTrue(comparator.compare("孟", "宋") < 0);
}
/**
* 不同长度
*/
@Test
public void testDifferentLength() {
Assert.assertTrue(comparator.compare("他奶奶的", "他奶奶的熊") < 0);
}
/**
* 和非汉字比较
*/
@Test
public void testNoneChinese() {
Assert.assertTrue(comparator.compare("a", "阿") < 0);
Assert.assertTrue(comparator.compare("1", "阿") < 0);
}
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") < 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") == 0);
}
/**
* 多音字(曾)
*/
@Test
public void testMultiSound() {
Assert.assertTrue(comparator.compare("曾经", "曾迪") > 0);
}
}
/**
* @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 comparator = new PinyinComparator();
/**
* 常用字
*/
@Test
public void testCommon() {
Assert.assertTrue(comparator.compare("孟", "宋") < 0);
}
/**
* 不同长度
*/
@Test
public void testDifferentLength() {
Assert.assertTrue(comparator.compare("他奶奶的", "他奶奶的熊") < 0);
}
/**
* 和非汉字比较
*/
@Test
public void testNoneChinese() {
Assert.assertTrue(comparator.compare("a", "阿") < 0);
Assert.assertTrue(comparator.compare("1", "阿") < 0);
}
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") < 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") == 0);
}
/**
* 多音字(曾)
*/
@Test
public void testMultiSound() {
Assert.assertTrue(comparator.compare("曾经", "曾迪") > 0);
}
}
我的这样严格的拼音排序还是有有待改进的地方,看上面测试代码的最后一个测试,就会发现:程序不会根据语境来判断多音字的拼音,仅仅是简单的取多音字的第一个拼音。
笔画排序
要按笔画排序,就要实现笔画比较器。
Java代码
class StokeComparator implements Comparator
class StokeComparator implements Comparator
如果有个方法可以求得汉字的笔画数,上面的功能就很容易实现。如何求一个汉字的笔画数?最容易想到的就是查表法。建一个汉字笔画数表,如:
汉字 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程序
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.IOException;
import java.io.PrintWriter;
public class ChineseCoder {
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter("Chinese.csv");
// 基本汉字
for(char c = 0x4E00; c <= 0x9FA5; c++) {
out.println((int)c + "," + c);
}
out.flush();
out.close();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.IOException;
import java.io.PrintWriter;
public class ChineseCoder {
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter("Chinese.csv");
// 基本汉字
for(char c = 0x4E00; c <= 0x9FA5; c++) {
out.println((int)c + "," + c);
}
out.flush();
out.close();
}
}
初始化笔画数
从Excel排序过后的Chinese.csv文件来看,排好序的文件还是有一定规律的。在文件的第9行-12行可以看出:逐行扫描的时候,当unicode会变小了,笔画数也就加1。
20059,乛
20101,亅
19969,丁
19970,丂
用下面的Java程序分析吧。
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Stroke {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new File("Chinese.csv"));
PrintWriter out = new PrintWriter("ChineseStroke.csv");
String oldLine = "999999";
int stroke = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.compareTo(oldLine) < 0) {
stroke++;
}
oldLine = line;
out.println(line + "," + stroke);
}
out.flush();
out.close();
in.close();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Stroke {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new File("Chinese.csv"));
PrintWriter out = new PrintWriter("ChineseStroke.csv");
String oldLine = "999999";
int stroke = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.compareTo(oldLine) < 0) {
stroke++;
}
oldLine = line;
out.println(line + "," + stroke);
}
out.flush();
out.close();
in.close();
}
}
上面用的这个规律有问题吗?有问题,从ChineseStroke.csv文件抽取最后几个汉字就发现,笔画数不对。为什么呢?
* 笔画数可能不是连续的。
* n+1笔画数的最小Unicode码可能比n笔画数的最大Unicode码要大
我们要人工核对ChineseStroke文件,但只要核对在笔画变化的那几个汉字的笔画数。最后,我发现,只有笔画数多于30的少数几个汉字的笔画数不对。核对并矫正笔画数后,用Excel按Unicode重新排序,去掉汉字和Unicode两列,只保留笔画数那列,得到Stroke.csv文件。
求得笔画数的方法和笔画比较器方法
求得笔画数的方法测试代码:
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.Chinese;
public class StrokeTest {
Chinese chinese;
@Before
public void setUp() {
chinese = new Chinese();
}
@Test
public void testStroke() {
assertEquals(1, chinese.stroke('一'));
}
@Test
public void testStroke2() {
assertEquals(2, chinese.stroke('二'));
}
@Test
public void testStroke16() {
assertEquals(16, chinese.stroke('龍'));
}
@Test
public void testStrokeABC() {
assertEquals(-1, chinese.stroke('a'));
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.Chinese;
public class StrokeTest {
Chinese chinese;
@Before
public void setUp() {
chinese = new Chinese();
}
@Test
public void testStroke() {
assertEquals(1, chinese.stroke('一'));
}
@Test
public void testStroke2() {
assertEquals(2, chinese.stroke('二'));
}
@Test
public void testStroke16() {
assertEquals(16, chinese.stroke('龍'));
}
@Test
public void testStrokeABC() {
assertEquals(-1, chinese.stroke('a'));
}
}
求得笔画数的方法代码
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
public class StrokeComparator implements Comparator {
public int compare(String o1, String o2) {
Chinese chinese = new Chinese();
for (int i = 0; i < o1.length() && i < o2.length(); i++) {
int codePoint1 = o1.codePointAt(i);
int codePoint2 = o2.codePointAt(i);
if (codePoint1 == codePoint2)
continue;
int stroke1 = chinese.stroke(codePoint1);
int stroke2 = chinese.stroke(codePoint2);
if (stroke1 < 0 || stroke2 < 0) {
return codePoint1 - codePoint2;
}
if (stroke1 != stroke2) {
return stroke1 - stroke2;
}
}
return o1.length() - o2.length();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
public class StrokeComparator implements Comparator {
public int compare(String o1, String o2) {
Chinese chinese = new Chinese();
for (int i = 0; i < o1.length() && i < o2.length(); i++) {
int codePoint1 = o1.codePointAt(i);
int codePoint2 = o2.codePointAt(i);
if (codePoint1 == codePoint2)
continue;
int stroke1 = chinese.stroke(codePoint1);
int stroke2 = chinese.stroke(codePoint2);
if (stroke1 < 0 || stroke2 < 0) {
return codePoint1 - codePoint2;
}
if (stroke1 != stroke2) {
return stroke1 - stroke2;
}
}
return o1.length() - o2.length();
}
}
笔画比较器测试
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
笔画比较器
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
这是我能找到的关于汉字编码排序和比较器最全的文章了!非常受益,谢谢作者!~~~
关键字: java实战
摘要:在Java中,对一个数组或列表(在本文中统称为集合)中的元素排序,是一个很经常的事情。好在Sun公司在Java库中实现了大部分功能。如果集合中的元素实现了Comparable接口,调用Array或Collections的静态(static)方法sort,就可以直接对集合排序。程序员用不同的方式实现了Comparator接口,就可以用各自不同的方式排序。对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画。本文就讲述如何实现这两种不同的比较器(Comparator)。
作者:Jeff 发表于:2007年12月21日 11:27 最后更新于: 2007年12月21日 12:38
版权声明:可以任意转载,转载时请务必以超链接形式标明文章 原始出处和作者信息及本版权声明。
[url]http://www.blogjava.net/jeff-lau/archive/2007/12/21/169257.html [/url]
排序概述
在Java中,对一个数组或列表(在本文中统称为集合)中的元素排序,是一个很经常的事情。好在Sun公司在Java库中实现了大部分功能。如果集合中的元素实现了Comparable接口,调用以下的静态(static)方法,就可以直接对集合排序。
Java代码
// 数组排序方法
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
java.util.Arrays.sort(type[] a);
// 数组排序方法
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
java.util.Arrays.sort(type[] a);
Java代码
// 列表
public static void sort(List list)
// 列表
public static void sort(List list)
以上的这些排序方式能满足大部分应用。但集合中的元素没有实现Comparable接口,或者集合中的元素要按一种特别的方式排序,这要怎么办?Sun公司早就想到了,并在Java库中提供上面两个方法的重载。
Java代码
// 数组排序方法。
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
public static void sort(T[] a, Comparator c)
// 数组排序方法。
// 数组中的元素可以是像int这样的原生类型(primitive type), 也可以是像String这样实现了Comparable接口的类型,这里用type表示。
public static void sort(T[] a, Comparator c)
Java代码
// 列表
public static void sort(List list, Comparator c)
// 列表
public static void sort(List list, Comparator c)
只要实现了Comparator接口,就可以按程序员自己的意思去排序了。对于包含汉字的字符串来说,排序的方式主要有两种:一种是拼音,一种是笔画。汉字是通过一定的编码方式存储在计算机上的,主要的编码有:Unicdoe、GB2312和GBK等。
Unicode 编码中的汉字
Unicode中编码表分为两块,一个是基本的,一个是辅助的。现在的大多数操作系统还不支持Unicode中辅助区域中的文字,如WinXp。
在Java中的字符就是Unicode码表示的。对于Unicode基本区域中的文字,用两个字节的内存存储,用一个char表示,而辅助区域中的文字用 4个字节存储,因此辅助区域中的就要用两个char来表示了(表一种蓝色底就是辅助区域中的文字)。一个文字的unicode编码,在Java中统一用 codePoint(代码点)这个概念。
中文和日文、韩文一样是表意文字,在Unicode中,中日韩三国(东亚地区)的文字是统一编码的。CJK代表的就是中日韩。在这里,我把这3中文字,都作为汉字处理了。(日语和韩语可能就是从汉语中衍生的吧!)
汉字在Unicode中的分布大致如下表:
首字编码 尾字编码 个数
基本汉字 U4E00 U9FBF 20928
异性字 UF900 UFAFF 512
扩展A U3400 U4D8F 512
扩展B U20000 U2A6DF 42720
补充 U2F800 U2FA1F 544
其他 ...
表一
在这些编码区间,有些编码是保留的。
GB2312编码
GB2312是中华人民共和国最早的计算机汉字编码方式。大概有6000多个汉字,这些汉字是按拼音顺序编码的。这6000多个汉字都是简体中文字。
GBK编码
GB2312的扩展,并兼容GB2312。扩展后的汉字大概有2万多个,其中有简体汉字也有繁体汉字。
拼音排序
拼音有好几种方式,其中最主要的是中华人民共和国的汉语拼音 Chinese Phonetic。对汉字的排序有两种:一种是宽松的,能够按拼音排序最常用的汉字,另一种是严格的,能够按拼音排序绝大部分大部分汉字。
宽松的拼音排序法
原理:汉字最早是GB2312编码,收录了六千多个汉字,是按拼音排序的,编码是连续的。后来出现了GBK编码,对GB2312进行了扩展,到了两万多汉字,并且兼容GB2312,也就是说GB2312中的汉字编码是原封不动搬到GBK中的(在GBK编码中[B0-D7]区中)。
如果我们只关心这6000多个汉字的顺序,就可以用下面的方法实现汉字宽松排序。
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class PinyinSimpleComparator implements Comparator {
public int compare(String o1, String o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class PinyinSimpleComparator implements Comparator {
public int compare(String o1, String o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
}
}
在对[孙, 孟, 宋, 尹, 廖, 张, 徐, 昆, 曹, 曾,怡]这几个汉字排序,结果是:[曹, 昆, 廖, 孟, 宋, 孙, 徐, 尹, 曾, 张, 怡]。最后一个 怡 有问题,不该排在最后的。
注意:这个程序有两个不足
* 由于gb2312中的汉字编码是连续的,因此新增加的汉字不可能再按照拼音顺序插入到已有的gb2312编码中,所以新增加的汉字不是按拼音顺序排的。
* 同音字比较的结果不等于0 。
下面的测试代码可以证明
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") > 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") != 0);
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") > 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") != 0);
}
严格的拼音排序法
为了解决宽松的拼音的两点不足,可以通过实现汉语拼音的函数来解决。goolge下看到sf上有个pinyin4j的项目,可以解决这个问题,pinyin4j的项目地址是:http://pinyin4j.sourceforge.net/。
实现代码:
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper;
public class PinyinComparator implements Comparator {
public int compare(String o1, String o2) {
for (int i = 0; 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[0];
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
import net.sourceforge.pinyin4j.PinyinHelper;
public class PinyinComparator implements Comparator {
public int compare(String o1, String o2) {
for (int i = 0; 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[0];
}
}
测试:
Java代码
/**
* @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 comparator = new PinyinComparator();
/**
* 常用字
*/
@Test
public void testCommon() {
Assert.assertTrue(comparator.compare("孟", "宋") < 0);
}
/**
* 不同长度
*/
@Test
public void testDifferentLength() {
Assert.assertTrue(comparator.compare("他奶奶的", "他奶奶的熊") < 0);
}
/**
* 和非汉字比较
*/
@Test
public void testNoneChinese() {
Assert.assertTrue(comparator.compare("a", "阿") < 0);
Assert.assertTrue(comparator.compare("1", "阿") < 0);
}
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") < 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") == 0);
}
/**
* 多音字(曾)
*/
@Test
public void testMultiSound() {
Assert.assertTrue(comparator.compare("曾经", "曾迪") > 0);
}
}
/**
* @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 comparator = new PinyinComparator();
/**
* 常用字
*/
@Test
public void testCommon() {
Assert.assertTrue(comparator.compare("孟", "宋") < 0);
}
/**
* 不同长度
*/
@Test
public void testDifferentLength() {
Assert.assertTrue(comparator.compare("他奶奶的", "他奶奶的熊") < 0);
}
/**
* 和非汉字比较
*/
@Test
public void testNoneChinese() {
Assert.assertTrue(comparator.compare("a", "阿") < 0);
Assert.assertTrue(comparator.compare("1", "阿") < 0);
}
/**
* 非常用字(怡)
*/
@Test
public void testNoneCommon() {
Assert.assertTrue(comparator.compare("怡", "张") < 0);
}
/**
* 同音字
*/
@Test
public void testSameSound() {
Assert.assertTrue(comparator.compare("怕", "帕") == 0);
}
/**
* 多音字(曾)
*/
@Test
public void testMultiSound() {
Assert.assertTrue(comparator.compare("曾经", "曾迪") > 0);
}
}
我的这样严格的拼音排序还是有有待改进的地方,看上面测试代码的最后一个测试,就会发现:程序不会根据语境来判断多音字的拼音,仅仅是简单的取多音字的第一个拼音。
笔画排序
要按笔画排序,就要实现笔画比较器。
Java代码
class StokeComparator implements Comparator
class StokeComparator implements Comparator
如果有个方法可以求得汉字的笔画数,上面的功能就很容易实现。如何求一个汉字的笔画数?最容易想到的就是查表法。建一个汉字笔画数表,如:
汉字 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程序
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.IOException;
import java.io.PrintWriter;
public class ChineseCoder {
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter("Chinese.csv");
// 基本汉字
for(char c = 0x4E00; c <= 0x9FA5; c++) {
out.println((int)c + "," + c);
}
out.flush();
out.close();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.IOException;
import java.io.PrintWriter;
public class ChineseCoder {
public static void main(String[] args) throws IOException {
PrintWriter out = new PrintWriter("Chinese.csv");
// 基本汉字
for(char c = 0x4E00; c <= 0x9FA5; c++) {
out.println((int)c + "," + c);
}
out.flush();
out.close();
}
}
初始化笔画数
从Excel排序过后的Chinese.csv文件来看,排好序的文件还是有一定规律的。在文件的第9行-12行可以看出:逐行扫描的时候,当unicode会变小了,笔画数也就加1。
20059,乛
20101,亅
19969,丁
19970,丂
用下面的Java程序分析吧。
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Stroke {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new File("Chinese.csv"));
PrintWriter out = new PrintWriter("ChineseStroke.csv");
String oldLine = "999999";
int stroke = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.compareTo(oldLine) < 0) {
stroke++;
}
oldLine = line;
out.println(line + "," + stroke);
}
out.flush();
out.close();
in.close();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.preface;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Stroke {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Scanner in = new Scanner(new File("Chinese.csv"));
PrintWriter out = new PrintWriter("ChineseStroke.csv");
String oldLine = "999999";
int stroke = 0;
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.compareTo(oldLine) < 0) {
stroke++;
}
oldLine = line;
out.println(line + "," + stroke);
}
out.flush();
out.close();
in.close();
}
}
上面用的这个规律有问题吗?有问题,从ChineseStroke.csv文件抽取最后几个汉字就发现,笔画数不对。为什么呢?
* 笔画数可能不是连续的。
* n+1笔画数的最小Unicode码可能比n笔画数的最大Unicode码要大
我们要人工核对ChineseStroke文件,但只要核对在笔画变化的那几个汉字的笔画数。最后,我发现,只有笔画数多于30的少数几个汉字的笔画数不对。核对并矫正笔画数后,用Excel按Unicode重新排序,去掉汉字和Unicode两列,只保留笔画数那列,得到Stroke.csv文件。
求得笔画数的方法和笔画比较器方法
求得笔画数的方法测试代码:
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.Chinese;
public class StrokeTest {
Chinese chinese;
@Before
public void setUp() {
chinese = new Chinese();
}
@Test
public void testStroke() {
assertEquals(1, chinese.stroke('一'));
}
@Test
public void testStroke2() {
assertEquals(2, chinese.stroke('二'));
}
@Test
public void testStroke16() {
assertEquals(16, chinese.stroke('龍'));
}
@Test
public void testStrokeABC() {
assertEquals(-1, chinese.stroke('a'));
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.Chinese;
public class StrokeTest {
Chinese chinese;
@Before
public void setUp() {
chinese = new Chinese();
}
@Test
public void testStroke() {
assertEquals(1, chinese.stroke('一'));
}
@Test
public void testStroke2() {
assertEquals(2, chinese.stroke('二'));
}
@Test
public void testStroke16() {
assertEquals(16, chinese.stroke('龍'));
}
@Test
public void testStrokeABC() {
assertEquals(-1, chinese.stroke('a'));
}
}
求得笔画数的方法代码
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
public class StrokeComparator implements Comparator {
public int compare(String o1, String o2) {
Chinese chinese = new Chinese();
for (int i = 0; i < o1.length() && i < o2.length(); i++) {
int codePoint1 = o1.codePointAt(i);
int codePoint2 = o2.codePointAt(i);
if (codePoint1 == codePoint2)
continue;
int stroke1 = chinese.stroke(codePoint1);
int stroke2 = chinese.stroke(codePoint2);
if (stroke1 < 0 || stroke2 < 0) {
return codePoint1 - codePoint2;
}
if (stroke1 != stroke2) {
return stroke1 - stroke2;
}
}
return o1.length() - o2.length();
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility;
import java.util.Comparator;
public class StrokeComparator implements Comparator {
public int compare(String o1, String o2) {
Chinese chinese = new Chinese();
for (int i = 0; i < o1.length() && i < o2.length(); i++) {
int codePoint1 = o1.codePointAt(i);
int codePoint2 = o2.codePointAt(i);
if (codePoint1 == codePoint2)
continue;
int stroke1 = chinese.stroke(codePoint1);
int stroke2 = chinese.stroke(codePoint2);
if (stroke1 < 0 || stroke2 < 0) {
return codePoint1 - codePoint2;
}
if (stroke1 != stroke2) {
return stroke1 - stroke2;
}
}
return o1.length() - o2.length();
}
}
笔画比较器测试
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
笔画比较器
Java代码
/**
* @author Jeff
*
* Copyright (c) 复制或转载本文,请保留该注释。
*/
package chinese.utility.test;
import java.util.Comparator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import chinese.utility.StrokeComparator;
public class StrokeComparatorTest {
private Comparator comparator;
@Before
public void setUp() {
comparator = new StrokeComparator();
}
/**
* 相同笔画数
*/
@Test
public void testCompareEquals() {
Assert.assertTrue(comparator.compare("一", "丨") == 0);
}
/**
* 不同笔画数
*/
@Test
public void testCompare() {
Assert.assertTrue(comparator.compare("一", "二") < 0);
Assert.assertTrue(comparator.compare("唔", "马") > 0);
}
/**
* 长度不同
*/
@Test
public void testCompareDefficultLength() {
Assert.assertTrue(comparator.compare("二", "二一") < 0);
}
/**
* 非汉字的比较
*/
@Test
public void testABC() {
Assert.assertTrue(comparator.compare("一", "a") > 0);
Assert.assertTrue(comparator.compare("a", "b") < 0);
}
}
这是我能找到的关于汉字编码排序和比较器最全的文章了!非常受益,谢谢作者!~~~
发表评论
-
java模拟点击
2020-05-12 18:26 457try { Dimension screenS ... -
jekins集成maven发布项目过程中遇到的坑
2017-04-05 14:33 1713背景: 用maven构建项目之后,每次需要部署集成测试环 ... -
logback配置
2015-08-17 15:30 661<?xml version="1.0" ... -
javamail
2014-07-09 21:35 793http://blog.csdn.net/zapldy/art ... -
jdbc批量插入数据
2013-11-10 11:35 852以下过程网上看到,备份一下语法而已 Connection co ... -
jdbc获得生成记录主键
2013-11-10 11:18 704在网上看到的,备份一下而已 Connection conn = ... -
jdbc调用存储过程
2013-11-10 11:12 670只是把调用过程备份一下 Connection conn = ... -
十六进制转字符串
2013-07-04 22:09 1343记录一下十六进制转字符串,以备以后使用方便 //十六进制转字符 ... -
模拟自动登录并发表日志
2012-12-11 20:11 1205公司要求每天都需要写 ... -
List.toArray()强转对象数组
2012-06-13 15:18 1496假设现在有一个集合list,里面装的都是对象A,如下代码进行强 ... -
正则表达式
2012-06-05 13:53 1如果你曾经用过Perl或任 ... -
关于LinkedHashMap的一些简单实验
2012-05-15 14:53 926同为实现了Map接口的类,LinedHashMap在迭代的时候 ... -
UUID
2012-05-14 15:34 1488转自http://popwang.iteye.com/blog ... -
eclipse install memory analyzer
2012-05-02 16:16 1083安装地址 http://download.eclipse.or ... -
java加密解密算法记录
2012-04-13 14:56 9921以下内容均摘自我买的书籍《java加密与解密的艺术》作者 梁栋 ... -
common email发送邮件
2012-03-06 16:56 1613项目地址:http://commons.apache.org/ ... -
java实现压缩和解压缩
2012-03-01 16:17 1113转自于站内兄弟的文章:http://wallimn.iteye ... -
java算法记录
2012-02-07 19:12 844package com.algorithm; impor ... -
java中yield(),sleep()以及wait()的区别
2012-02-07 10:30 1002转自http://xiechengfa.iteye.com/b ... -
oracle调用java
2011-12-27 15:18 1477修改别人写的oracle数据库调用java代码,换了一个环境, ...
相关推荐
综上所述,二叉排序树和霍夫曼编码树都是基于二叉树的数据结构,但它们的用途和设计原则有所不同。二叉排序树主要用于高效地进行查找、插入和删除操作,而霍夫曼编码树则是为了实现数据的高效压缩。学习这两个概念有...
GBK、BIG5等字符集的编码规则和排序方法都基于字节的数值大小,这为我们提供了明确的排序依据。同时,掌握不同编码之间的转换规则也能够帮助我们在跨平台、跨语言的环境中更有效地处理字符数据。希望本文能为开发者...
在信息传输和存储领域,Huffman编码被广泛应用于文本、图像和音频等数据的压缩。解码则是将经过Huffman编码的压缩数据恢复成原始数据的过程。 首先,我们来理解Huffman编码的基本原理。Huffman编码的核心是建立一个...
总之, Solaris 的编码格式更改是一个涉及多个环境变量和系统配置的过程,需要谨慎操作以确保系统能正确地显示和处理各种语言的文本。通过理解这些概念,你可以更有效地管理和定制你的 Solaris 系统以适应不同的语言...
在提供的压缩包文件中,除了哈夫曼编码器的源码和文档外,还包含了各种内部排序算法的源码。这可以帮助学习者深入理解这些算法的实现细节,通过实际运行代码,观察不同算法在不同数据集上的表现,有助于提高对排序...
在进行CAN总线的通讯过程中,经常看到CAN总线的编码格式有2种定义,究竟2种格式有什么区别呢,如何判断2种格式,进行有效正确的配置和解析,本文告诉你答案。
“排序编码表.txt”是一个宝贵的资源,它提供了Unicode字符的完整视图,便于开发人员和研究人员理解、操作和分析文本数据。通过深入理解和利用Unicode编码表,我们可以构建更加健壮、全球化友好的软件系统,促进不同...
在这个实验中,我们将深入理解这两种编码方式,并结合一阶概率分布和排序等概念。 首先,让我们谈谈香农编码。香农编码是由美国数学家克劳德·香农提出的,它是信息论的基础之一。香农定理阐述了在有噪声信道上通信...
位排序和快速排序是两种不同的排序算法,它们在处理大量数据时各有特点。在这个场景中,我们关注...对于这个案例中的30万个数字,快速排序可能是更明智的选择,同时,确保代码注释使用正确的编码格式,以防止显示问题。
使用ICU进行编码转换的优势在于它的权威性和全面性,能够处理各种常见及罕见的编码格式。 在ICU中,我们可以使用`ucnv`组件来进行编码转换。例如,将UTF-8编码的文本转换为GB2312,可以通过以下步骤: 1. 创建源...
在IT领域,尤其是在数据处理和文件管理中,排序是一个至关重要的操作。对于数字的排序,如果直接按照字典顺序,可能会出现不符合预期的结果,比如数字10会排在数字2之前。为了解决这个问题,我们可以采取特定的编码...
文档中保存了市级行政区域编码按字母分组排序的json,可用于前端做为常量,你自己可以在网上下载的,也可以用积分来我这里下载
快速排序算法的编码和优化 快速排序的基本思路是: 1. 先通过第一趟排序,将数组原地划分为两部分,其中一部分的所有数据都小于另一部分的所有数据。原数组 被划分为2份 2. 通过递归的处理, 再对原数组分割的两...
首先,我们要明白在Java中,默认的字符串排序是基于Unicode编码的,这可能会导致中文字符与英文字符混合排序时出现问题。例如,英文字符通常会排在中文字符前面,因为它们的Unicode值更低。为了解决这个问题,我们...
哈夫曼编码是一种变长前缀编码方法,它可以根据信源符号的概率分布计算信源熵和编码效率。本文将详细介绍哈夫曼编码的原理、步骤和实现方法。 哈夫曼编码的原理 哈夫曼编码的原理是基于信源符号的概率分布。设信源...
由于汉字与数字在数据结构和编码上的本质差异,混合排序需要特定的算法和技术来实现。以下将详细介绍汉字和数字混合排序的相关知识点。 首先,我们要了解汉字和数字在计算机中的存储方式。汉字通常使用Unicode编码...
arraysort 对一维数组进行排序 decto 将十进制数字转成其它进制字符串 getsep 得到指定符号分隔开的文本数组 hexdecode 将16进制字符串以指定字符集进行解码成字符 hexencode 将字符串指定字符集进行编码成16进制...
7. **快速排序**:虽然Huffman编码本身并不涉及快速排序,但在这个实现中可能用到了快速排序来对字符频率进行排序,因为这是构建最小堆的一种有效方法。快速排序是一种高效的排序算法,平均时间复杂度为O(n log n)。...