目录

  • 引言
  • 一、方案一
    • 1、依赖引入
    • 2、完整代码(含注解)
    • 3、验证测试
      • 测试 isHanZi()
      • 测试 compareCharWithHanZi()
      • 测试 compareStringWithHanZi()
      • 测试 getFirstStringFromHanyuPinyinStringArray()
    • 4、排序示例
      • String数组排序
      • 复杂对象排序
  • 二、方案二
    • 1、依赖引入
    • 2、使用演示
    • 3、排序示例
      • 复杂对象排序

引言

基于pinyin4j依赖(net.sourceforge.pinyin4j)和icu4j依赖(com.ibm.icu.text),并且借鉴Java 8中字符串比对的源码给出了两套方案来判断、比较并排序处理含有中文/汉字字符的字符串,兼容性和通用性较好,并且给出了排序示例和详细的方法注解。
 
如需浏览,请详见目录,即可快速定位到需要的内容。之后将会持续修复Bug、并且更新、优化完善,如需及时收到最新内容,记得关注、收藏一下┗|`O′|┛ 嗷~~


一、方案一

比较处理过程直观,便于自定义,在一些细节处理上可以自行优化或加入符合实际需求的逻辑处理(支持数字排在最前,英文字母其次,汉字则按照拼音进行排序)

1、依赖引入

利用Maven引入pinyin4j依赖:

<dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version>
</dependency>

2、完整代码(含注解)

该工具类移植性,代码复用性较好,且支持含单个或多个中文/汉字、英文、数字以及特殊字符杂糅的字符串大小比对(支持数字排在最前,英文字母其次,汉字则按照拼音进行排序);且将以下代码内容复制后直接粘贴到项目中即可使用!

import net.sourceforge.pinyin4j.PinyinHelper;import java.util.Objects;/*** 比对工具(支持中文/汉字比对)** @author JZY*/
public class CompareUtil {private static final String REGEX = "[\u4e00-\u9fa5]";/*** 判断单个字符是否为汉字** @param c 字符* @return 是否为汉字*/public static boolean isHanZi(char c) {return String.valueOf(c).matches(REGEX);}/*** 比对两个字符(可含汉字)大小** @param c1 字符1* @param c2 字符2* @return 两个字符相差的大小(返回结果大于0表示第一个字符大,返回结果小于0表示第二个字符大,返回结果等于0表示两个字符一样大)*          (针对两个读音和音调相同的中文/汉字字符,再次进行常规的编码大小比对)*/public static int compareCharWithHanZi(char c1, char c2) {boolean b1 = isHanZi(c1);boolean b2 = isHanZi(c2);if (b1 && b2) {int result = Objects.requireNonNull(getFirstStringFromHanyuPinyinStringArray(c1)).compareTo(Objects.requireNonNull(getFirstStringFromHanyuPinyinStringArray(c2)));return result != 0 ? result : Character.compare(c1, c2);} else {return Character.compare(c1, c2);}}/*** 判断两个字符串(可含汉字)大小** @param string1 字符串1* @param string2 字符串2* @return 两个字符串大小的比对结果(返回1表示第一个字符串大,返回-1表示第二个字符串大,返回0表示两个字符串一样大)*/public static int compareStringWithHanZi(String string1, String string2) {char[] charArray1 = string1.toCharArray();char[] charArray2 = string2.toCharArray();int length1 = charArray1.length;int length2 = charArray2.length;int limit = Math.min(length1, length2);int result;for (int i = 0; i < limit; i++) {result = compareCharWithHanZi(charArray1[i], charArray2[i]);if (result != 0) {return result > 0 ? 1 : -1;}}if (length1 == length2) {return 0;}return length1 > length2 ? 1 : -1;}/*** 获取单个字符的第一个汉语拼音** @param c 字符* @return 汉字字符的第一个汉语拼音*/public static String getFirstStringFromHanyuPinyinStringArray(char c) {String[] strings = PinyinHelper.toHanyuPinyinStringArray(c);if (strings != null) {return strings[0];} else {return null;}}
}

3、验证测试

定义一些字符和字符串

char c1 = 'c';char c2 = 'k';char c3 = '码';char c4 = '大';char c5 = '衣';char c6 = '依';char c7 = '#';char c8 = 'π';String string1 = "李四";String string2 = "张三";String string3 = "123王s五";String string4 = "12a3王s五";String string5 = "123王z五";String string6 = "123王z五";String string7 = "一一壹";String string8 = "一一医";

测试 isHanZi()

@Test
void isHanZi() {System.out.println(CompareUtil.isHanZi(c1));System.out.println(CompareUtil.isHanZi(c2));System.out.println(CompareUtil.isHanZi(c3));System.out.println(CompareUtil.isHanZi(c4));System.out.println(CompareUtil.isHanZi(c5));System.out.println(CompareUtil.isHanZi(c6));System.out.println(CompareUtil.isHanZi(c7));System.out.println(CompareUtil.isHanZi(c8));
}

测试结果符合预期

测试 compareCharWithHanZi()

@Test
void compareCharWithHanZi() System.out.println(CompareUtil.compareCharWithHanZi(c1, c2));System.out.println(CompareUtil.compareCharWithHanZi(c1, c3));System.out.println(CompareUtil.compareCharWithHanZi(c3, c4));System.out.println(CompareUtil.compareCharWithHanZi(c5, c6));System.out.println(CompareUtil.compareCharWithHanZi(c7, c8));
}

测试结果符合预期

测试 compareStringWithHanZi()

@Test
void compareStringWithHanZi() {System.out.println(CompareUtil.compareStringWithHanZi(string1, string2));System.out.println(CompareUtil.compareStringWithHanZi(string1, string3));System.out.println(CompareUtil.compareStringWithHanZi(string3, string5));System.out.println(CompareUtil.compareStringWithHanZi(string4, string5));System.out.println(CompareUtil.compareStringWithHanZi(string5, string6));System.out.println(CompareUtil.compareStringWithHanZi(string7, string8));
}

测试结果符合预期

测试 getFirstStringFromHanyuPinyinStringArray()

@Test
void getFirstStringFromHanyuPinyinStringArray() {System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c1));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c2));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c3));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c4));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c5));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c6));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c7));System.out.println(CompareUtil.getFirstStringFromHanyuPinyinStringArray(c8));
}

测试结果符合预期

4、排序示例

String数组排序

@Test
void compareList() {LinkedList<String> linkedList = new LinkedList<>();linkedList.add("张三");linkedList.add("李四");linkedList.add("王五");linkedList.add("赵六");linkedList.add("王二麻子");System.out.println("排序前:" + linkedList);linkedList.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return CompareUtil.compareStringWithHanZi(o1, o2);}});System.out.println("排序(升序)后:" + linkedList);
}

运行结果符合预期

如果要降序排序,将自定义比对器的返回结果取反即可:
return CompareUtil.compareStringWithHanZi(o1, o2);
修改为
return -CompareUtil.compareStringWithHanZi(o1, o2);
 
Tip:如果采用的是Java 8,即可使用Lambda表达式简化代码:
linkedList.sort((o1, o2) -> CompareUtil.compareStringWithHanZi(o1, o2));
此处的Lambda表达式甚至可以替换为方法参考,进一步简化代码:
linkedList.sort(CompareUtil::compareStringWithHanZi);
 
当然实际使用中,需要根据具体的业务需求来自定义Comparator,以上仅供参考!

复杂对象排序

先定义一个复杂对象

class User {private HashMap<String, Object> information;public User() {}public User(HashMap<String, Object> information) {this.information = information;}public HashMap<String, Object> getInformation() {return information;}public void setInformation(HashMap<String, Object> information) {this.information = information;}@Overridepublic String toString() {return "User{" +"information=" + information +'}';}
}
@Test
void compareObject() {User user1 = new User();HashMap<String, Object> hashMap1 = new HashMap<>();hashMap1.put("name", "张三");hashMap1.put("age", 25);user1.setInformation(hashMap1);User user2 = new User();HashMap<String, Object> hashMap2 = new HashMap<>();hashMap2.put("name", "李四");hashMap2.put("age", 20);user2.setInformation(hashMap2);User user3 = new User();HashMap<String, Object> hashMap3 = new HashMap<>();hashMap3.put("name", "王五");hashMap3.put("age", 30);user3.setInformation(hashMap3);LinkedList<User> linkedList = new LinkedList<>();linkedList.add(user1);linkedList.add(user2);linkedList.add(user3);System.out.println("排序前:" + linkedList);linkedList.sort(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return CompareUtil.compareStringWithHanZi(String.valueOf(o1.getInformation().get("name")), String.valueOf(o2.getInformation().get("name")));}});System.out.println("排序(升序)后:" + linkedList);
}

运行结果符合预期

如果要降序排序,将自定义比对器的返回结果取反即可:
return CompareUtil.compareStringWithHanZi(String.valueOf(o1.getInformation().get("name")), String.valueOf(o2.getInformation().get("name")));
修改为
return -CompareUtil.compareStringWithHanZi(String.valueOf(o1.getInformation().get("name")), String.valueOf(o2.getInformation().get("name")));
 
Tip:如果采用的是Java 8,即可使用Lambda表达式简化代码:
linkedList.sort((o1, o2) -> CompareUtil.compareStringWithHanZi(String.valueOf(o1.getInformation().get("name")), String.valueOf(o2.getInformation().get("name"))));
 
当然实际使用中,需要根据具体的业务需求来自定义Comparator,以上仅供参考!

二、方案二

使用com.ibm.icu.text.Collator进行排序(支持数字排在最前,英文字母其次,汉字则按照拼音进行排序)
 
效率较高,兼容性较好,但是封装程度较高,如果有特殊业务需求的比较规则,可能需要在比较逻辑层面上自行重写方法

1、依赖引入

利用Maven引入icu4j依赖:

<dependency><groupId>com.ibm.icu</groupId><artifactId>icu4j</artifactId><version>68.2</version>
</dependency>

2、使用演示

@Test
void comIbmIcuTextCollator() {List<String> stringList = new ArrayList<>();stringList.add("中国");stringList.add("中心");stringList.add("网易汽车");stringList.add("新民汽车网");stringList.add("钛媒体");stringList.add("瘾科技");stringList.add("昕薇网");stringList.add("安倍");System.out.println("使用com.ibm.icu.text.Collator进行排序");System.out.println("排序前:" + stringList);com.ibm.icu.text.Collator comIbmIcuTextCollator = com.ibm.icu.text.Collator.getInstance();stringList.sort(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return comIbmIcuTextCollator.compare(o1, o2);}});System.out.println("排序后:" + stringList);
}

运行结果

如果要降序排序,调换入参顺序即可:
return comIbmIcuTextCollator.compare(o1, o2);
修改为
return comIbmIcuTextCollator.compare(o2, o1);
 
Tip:如果采用的是Java 8,即可使用Lambda表达式简化代码:
stringList.sort(comIbmIcuTextCollator::compare);
 
当然实际使用中,需要根据具体的业务需求来自定义Comparator,以上仅供参考!

其中这里要特别指出的是,网上也有使用Java JDK中自带的Collator:java.text.Collator;但是并不建议使用!为了对比两者的区别,采用java.text.Collator对上面的数据再进行一次排序

@Test
void javaTextCollator() {List<String> stringList = new ArrayList<>();stringList.add("中国");stringList.add("中心");stringList.add("网易汽车");stringList.add("新民汽车网");stringList.add("钛媒体");stringList.add("瘾科技");stringList.add("昕薇网");stringList.add("安倍");System.out.println("使用java.text.Collator进行排序");System.out.println("排序前:" + stringList);java.text.Collator javaTextCollator = java.text.Collator.getInstance();stringList.sort(javaTextCollator::compare);System.out.println("排序后:" + stringList);
}

运行结果

发现“中国”、“中心”等字词排序位置不符合要求(理应是根据:数字排在最前,英文字母其次,汉字则按照拼音进行排序)
 
主要是因为java.text.Collator使用的顺序是其字符串包含的字符在指定语言当中的顺序(譬如中文汉字编著入库的顺序),是locale敏感的,为此不能做到任何环境下所有字符统一处理(可能同样的数据在不同的条件下处理结果不一致)

  • 为此建议使用com.ibm.icu.text.Collator;官网的介绍:ICU是成熟的,广泛使用的C/C++和Java库集,为软件应用程序提供Unicode和全球化支持。ICU具有广泛的可移植性,可以在所有平台上以及C/C++和Java软件之间为应用程序提供相同的结果。它还定义了数据和算法,以实现高效,一致的文本处理。这简化了高级处理,并确保所有兼容软件产生相同的结果。基于Unicode的全球化软件可最大程度地扩大市场范围并最小化成本。全球化软件可以一次构建和安装,但是可以处理来自世界各地的用户和来自世界各地的用户的文本,并适应他们的文化习俗。通过消除每种语言的构建,安装和维护更新,将成本降到最低
  • 为了保证兼容性和一致性,采用com.ibm.icu.text.Collator更具有优势!

3、排序示例

复杂对象排序

先定义一个复杂对象

/*** 用户实体类*/
class User implements Serializable {private static final long serialVersionUID = 1L;private HashMap<String, Object> information;public User() {}public User(HashMap<String, Object> information) {this.information = information;}public HashMap<String, Object> getInformation() {return information;}public void setInformation(HashMap<String, Object> information) {this.information = information;}@Overridepublic String toString() {return "User{" +"information=" + information +'}';}
}
@Test
void compareObjectUseComIbmIcuTextCollator() {User user1 = new User();HashMap<String, Object> hashMap1 = new HashMap<>();hashMap1.put("name", "张三");hashMap1.put("age", 25);user1.setInformation(hashMap1);User user2 = new User();HashMap<String, Object> hashMap2 = new HashMap<>();hashMap2.put("name", "李四");hashMap2.put("age", 20);user2.setInformation(hashMap2);User user3 = new User();HashMap<String, Object> hashMap3 = new HashMap<>();hashMap3.put("name", "王五");hashMap3.put("age", 30);user3.setInformation(hashMap3);LinkedList<User> linkedList = new LinkedList<>();linkedList.add(user1);linkedList.add(user2);linkedList.add(user3);System.out.println("排序前:" + linkedList);com.ibm.icu.text.Collator comIbmIcuTextCollator = com.ibm.icu.text.Collator.getInstance();linkedList.sort(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return comIbmIcuTextCollator.compare(o1.getInformation().get("name"), o2.getInformation().get("name"));}});System.out.println("排序(升序)后:" + linkedList);
}

运行结果符合预期

如果要降序排序,将比对器的返回结果取反即可:
return comIbmIcuTextCollator.compare(o1.getInformation().get("name"), o2.getInformation().get("name"));
修改为
return -comIbmIcuTextCollator.compare(o1.getInformation().get("name"), o2.getInformation().get("name"));
或者调换入参顺序
return comIbmIcuTextCollator.compare(o2.getInformation().get("name"), o1.getInformation().get("name"));
 
Tip:如果采用的是Java 8,即可使用Lambda表达式简化代码:
linkedList.sort((o1, o2) -> comIbmIcuTextCollator.compare(o1.getInformation().get("name"), o2.getInformation().get("name")));
 
当然实际使用中,需要根据具体的业务需求来自定义Comparator,以上仅供参考!


免责申明:相关文章及资料仅供学习交流使用,禁止一切不正当行为,如由此产生相关责任,自行承担
 
Tip:如需转发或引用相关内容,请务必附带原链接


如果对你有帮助的话,麻烦关注一波,并且点赞、收藏、转发一下哦o( ̄︶ ̄)o!如果有问题或者发现Bug欢迎提出反馈!

Java比较、排序处理含有中文/汉字的字符串相关推荐

  1. C++ 区分中文,非中文,截取含有中文的string字符串的两种方法

    C++ 区分中文,非中文,截取含有中文的string字符串的两种方法 方法一 根据中文在ASCII中的范围判断 方法二 把string转成wstring 转自: http://blog.51cto.c ...

  2. c++实现含有中文字符的字符串逆转,如:“我是小萌新”转换成“新萌小是我”

    一个中文字符占两字节,所以逆转也得两两字符进行逆转,如上图 可得出0和8,1和9,2和6,3和7进行下标交换 由此可得出以下代码: #include <iostream> #include ...

  3. Java字母笔顺_Android实现中文汉字笔划(笔画)、中文拼音排序、英文排序

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

  4. JAVA中下载文件名含有中文乱码一种少见的解决方案

    原始代码(未处理含中文和空格的文件名) @RestController public class FileController {@RequestMapping(value = "/down ...

  5. java截取中文_按字节截取混有中文汉字的字符串 中英文字符串截取

    [java]代码库import java.io.UnsupportedEncodingException; public class CutString { /** * 判断是否是一个中文汉字 * * ...

  6. 使用java语言pom依赖实现中文汉字转换拼音

    1.加入依赖 <!-- https://mvnrepository.com/artifact/com.belerweb/pinyin4j --><dependency>< ...

  7. java 汉字排序_java实现中文汉字的首字母排序

    java中可以排序的工具类和接口共有五个SortedMap .SortedSet.TreeMap .TreeSet和Collections,Collections中需要显式调用sort()方法. 事例 ...

  8. Java对List中的中文汉字进行排序以及多音字的处理

    默认按照首个汉字的拼音首字母进行升序排列 public static void main(String[] args) {List<Map<String, Object>> l ...

  9. 使用java将数字转化为中文汉字

    在实际开发过程中,会有遇到需要将传入的数字参数转化为汉字用来展示的情况,这里给出自己的思考,供给大家参考. public static void convert(int number) {//数字对应 ...

最新文章

  1. web设计经验七13步打造优雅的WEB字体
  2. 手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统(附源码+视频教程(第9节))...
  3. shell 脚本中while 循环只执行一次的问题
  4. TP框架中的A方法和R方法
  5. 如何解析比特币中的交易原始数据rawData
  6. SQL ---- 查询字段为逗号拼接的字符串
  7. JAVA ActiveMQ消息发送和接收
  8. java判断是否为linux,java判断是否Linux操作系统,判断OS操作系统类型工具类
  9. python中创建类的作用_Python中类的创建与使用详解
  10. 写出调试c语言程序的基本操作步骤,C语言程序设计基本步骤
  11. LOJ-10102(求A到B之间的割点)
  12. DICOM世界观·第二章:[2]像素操作
  13. go包base64解密
  14. 圆角半角数据库_SQL SERVER 全角和半角的解决方法
  15. 电子计算机显示屏不亮了,手把手教你电脑显示器不亮怎么办
  16. 计算机为什么要用补码?
  17. php获取h5视频直链,一种H5播放实时视频的方法与系统与流程
  18. 企业邮箱怎么开通?手机微信怎么绑定公司邮箱?
  19. Python+ASAquick+PSIPred蛋白质序列特征计算,ASAquick安装调用(Linux)
  20. 2038:最大数位置(题目来源于信息奥赛一本通官网)

热门文章

  1. Serializable是什么?(超详细讲解)
  2. 面渣逆袭:Java基础五十三问,快来看看有没有你不会的
  3. 用js求一张a4纸的厚度是0.104mm,珠穆朗玛峰是8848.43米,纸张折叠多少次超过珠穆朗玛峰?
  4. Android开发之USB数据通信
  5. 初学python,利用pandas读取excel出现乱码的问题
  6. Pytorch使用tensorboard监视网络训练过程
  7. ECN Trade:美国证券遭受冷落,债券外汇火热
  8. python画图-pylab
  9. c++的grpc例子
  10. Linux内核地址空间布局详解