当前位置: 首页 > article >正文

自定义中文排序在Java中的实现与注意事项

目录

  • 前言
  • 1. 基本知识
  • 2. 实战

前言

#1024程序员节 | 征文#

在这里插入图片描述

对于Java的基本知识推荐阅读:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

原先的Java中文排序,推荐阅读:Java或者前端 实现中文排序(调API的Demo)

以下文章主要记录自定义实战的中文排序

1. 基本知识

在Java中,中文排序通常涉及到使用Collator类来处理字符串的比较,确保根据汉字的拼音顺序进行排序

以下是详细分析和示例代码:(上述链接文章已经说清楚了,但先讲解一遍浅显的知识)

  • Collator类:用于比较字符串,特别适用于处理不同语言的排序
  • Locale:指定语言环境,影响排序规则
  • compare方法:用于比较两个字符串,根据指定的语言环境返回排序结果

示例代码如下:

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

public class ChineseSortingDemo {
    public static void main(String[] args) {
        // 创建一个包含中文字符串的列表
        List<String> chineseNames = new ArrayList<>();
        chineseNames.add("张三");
        chineseNames.add("李四");
        chineseNames.add("王五");
        chineseNames.add("赵六");

        // 获取中文排序的Collator实例
        Collator collator = Collator.getInstance(Locale.CHINESE);

        // 对列表进行排序
        Collections.sort(chineseNames, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return collator.compare(o1, o2); // 使用Collator比较
            }
        });

        // 输出排序后的结果
        System.out.println("排序后的中文名字:");
        for (String name : chineseNames) {
            System.out.println(name);
        }
    }
}

基本的逻辑如下:

  1. 导入所需类:导入Collator、ArrayList、Collections、Comparator和Locale
  2. 创建列表:使用ArrayList来存储中文字符串
  3. 获取Collator实例:使用Collator.getInstance(Locale.CHINESE)来获取适用于中文的排序规则
  4. 排序操作:通过Collections.sort()和自定义比较器,使用collator.compare()进行排序

2. 实战

自定义中文排序通常涉及对字符串的特定部分进行比较,以满足业务需求

主要目标是按照特定的中文数字(如“一”、“二”等)和名称排序,逻辑如下

  1. 提取数字部分:通过extractChineseNumber方法,从每个字符串中提取汉字数字部分。如果字符串包含汉字数字,则优先根据这些数字排序
  2. 排序优先级:首先,包含“类”的项优先。其次,根据提取的汉字数字进行排序,使用自定义比较器来定义排序规则。
    最后,对于没有数字的项,按字典顺序排序
  3. 使用流式处理:通过Java 8的流式API进行排序,增强代码的可读性和简洁性

注意事项

  • 字符集:确保输入的字符串都为标准汉字,避免因字符集不同导致的排序错误
  • 性能:在处理大量数据时,排序操作可能会影响性能,尽量优化提取逻辑
  • 多样性:考虑到可能存在的多种中文数字(如“零”)和不同的业务需求,确保排序规则的灵活性
  • 边界情况:处理字符串中可能没有汉字数字的情况,避免空指针异常
// 查询所有数据,不进行分页
List<Sort> allRecords = sortService.list(queryWrapper);

// 自定义中文数字排序规则
Comparator<String> chineseNumberComparator = (a, b) -> {
    String[] chineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};
    List<String> chineseNumberList = Arrays.asList(chineseNumbers);

    // 获取字符串的汉字数字部分
    String aNumberPart = extractChineseNumber(a);
    String bNumberPart = extractChineseNumber(b);

    // 如果都包含汉字数字部分,则按自定义顺序排序
    if (chineseNumberList.contains(aNumberPart) && chineseNumberList.contains(bNumberPart)) {
        return Integer.compare(chineseNumberList.indexOf(aNumberPart), chineseNumberList.indexOf(bNumberPart));
    }
    // 如果只有一个包含汉字数字,优先含有数字的排序
    else if (chineseNumberList.contains(aNumberPart)) {
        return -1;
    } else if (chineseNumberList.contains(bNumberPart)) {
        return 1;
    }
    // 如果都不包含汉字数字,则按字典序排序
    return a.compareTo(b);
};

// 对所有记录进行排序
List<Sort> sortedRecords = allRecords.stream()
    .sorted(Comparator.comparing((Sort record) -> {
            String sortNameRecord = record.getSortName();
            // 首先检查是否包含“类”,并提取类的前缀
            boolean hasClass = sortNameRecord.contains("类");
            // 确保包含“类”的项优先
            return hasClass ? 0 : 1; // 优先级
        })
        .thenComparing(Comparator.comparing((Sort record) -> {
            String sortNameRecord = record.getSortName();
            // 如果包含“类”,提取汉字数字部分并按其索引排序
            if (sortNameRecord.contains("类")) {
                return extractChineseNumber(sortNameRecord); // 提取汉字数字部分
            }
            return ""; // 没有类的项返回空字符串以放置在最后
        }, chineseNumberComparator)) // 按汉字数字排序
        .thenComparing(Comparator.comparing(Sort::getSortName)) // 按名称进行自然排序
    )
    .collect(Collectors.toList());

/**
 * 提取字符串中的汉字数字部分
 */
private String extractChineseNumber(String str) {
    String[] chineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};
    for (String number : chineseNumbers) {
        if (str.contains(number)) {
            return number;
        }
    }
    return ""; // 如果没有汉字数字,返回空字符串
}

截图如下:

在这里插入图片描述

最终效果如下:

在这里插入图片描述

测试的总体Demo如下:

import java.util.*;
import java.util.stream.Collectors;

public class CustomChineseSorting {
    public static void main(String[] args) {
        List<Sort> allRecords = sortService.list(queryWrapper);
        
        // 自定义中文数字排序规则
        Comparator<String> chineseNumberComparator = (a, b) -> {
            String[] chineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "零"};
            List<String> chineseNumberList = Arrays.asList(chineseNumbers);

            String aNumberPart = extractChineseNumber(a);
            String bNumberPart = extractChineseNumber(b);

            if (chineseNumberList.contains(aNumberPart) && chineseNumberList.contains(bNumberPart)) {
                return Integer.compare(chineseNumberList.indexOf(aNumberPart), chineseNumberList.indexOf(bNumberPart));
            } else if (chineseNumberList.contains(aNumberPart)) {
                return -1;
            } else if (chineseNumberList.contains(bNumberPart)) {
                return 1;
            }
            return a.compareTo(b);
        };

        // 对所有记录进行排序
        List<Sort> sortedRecords = allRecords.stream()
            .sorted(Comparator.comparing((Sort record) -> {
                    String sortNameRecord = record.getSortName();
                    return sortNameRecord.contains("类") ? 0 : 1;
                })
                .thenComparing(Comparator.comparing((Sort record) -> {
                    String sortNameRecord = record.getSortName();
                    if (sortNameRecord.contains("类")) {
                        return extractChineseNumber(sortNameRecord);
                    }
                    return ""; 
                }, chineseNumberComparator))
                .thenComparing(Comparator.comparing(Sort::getSortName))
            )
            .collect(Collectors.toList());

        // 输出排序后的结果
        sortedRecords.forEach(record -> System.out.println(record.getSortName()));
    }

    // 提取字符串中的汉字数字部分
    private static String extractChineseNumber(String str) {
        String[] chineseNumbers = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};
        for (String number : chineseNumbers) {
            if (str.contains(number)) {
                return number;
            }
        }
        return ""; 
    }
}

主要的注意事项如下:

  • 处理多个汉字数字
    若需要处理更大的数字(如“十一”、“十二”等),可进一步扩展extractChineseNumber方法,以支持更复杂的模式
  • 兼容性排序
    可以考虑为英文字符或其他语言字符设置不同的排序逻辑,以满足多语言应用的需求
  • 负数处理
    如果存在负数表示,可以在提取汉字数字时加入相关逻辑

http://www.kler.cn/news/361352.html

相关文章:

  • 力扣 困难 52.N皇后II
  • 【计网】理解TCP全连接队列与tcpdump抓包
  • Ubuntu 使用命令克隆和恢复SD卡
  • Java中消息队列
  • 揭秘Git合并机制:为何先commit后pull再push,避免代码覆盖的真相
  • 大学生项目竞赛:如何通过面试选拔优秀队友
  • redis的bitmap实现用户签到天数统计
  • 吃透高并发模型与RPC框架,拿下大厂offer!!!
  • VuePress的基本常识
  • HTML基本语法
  • 【电子元件】光通量和色温 (欧司朗LED灯珠 KW3 CGLNM1.TG命名规则)
  • 本币接口服务
  • 对比学习论文随笔 1:正负样本对(Contrastive Learning 基础论文篇)
  • Maven--架构项目管理工具
  • 基于知识图谱的美食推荐系统
  • 《普通逻辑》学习记录——引论
  • 【880线代】线性代数一刷错题整理
  • 裸指针的六个问题
  • 如何提高 YoloDotNet 图像目标检测的准确率?
  • 双碳目标下储能产业新趋势与架构
  • openssl所有版本源码下载链接
  • KafkaTools 3配置 SASL SSL双重认证
  • 基于单片机优先级的信号状态机设计
  • 一键找出图像中物体的角点(论文复现)
  • 【进阶OpenCV】 (22) --年龄性别预测
  • LeetCode Hot 100:滑动窗口