Java中使用Collator实现对象List按照中文姓名属性进行A-Z的排序实现
场景
Java接口中返回的包含中文姓名属性的实体的List,需要按照A-Z的中文顺序进行排序后返回。
可以使用Collator这个类。
Collator
Collator是java.text 包中的一个抽象类,专门用于执行与语言环境相关的字符串比较。
它能够根据特定语言或地区的规则对字符串进行排序和比较,
解决了简单按Unicode码点比较不适用于自然语言排序的问题
1. 核心作用
语言敏感的字符串比较:支持拼音、笔画等本地化排序规则
Unicode标准实现:符合CLDR(Common Locale Data Repository)规范
2. 关键构造方法
getInstance() 默认语言环境的比较器 Collator.getInstance()
getInstance(Locale) 指定语言环境
Locale.CHINA(中文)
Locale.TAIWAN(繁体)
3. 排序强度控制(重要)
collator.setStrength(Collator.PRIMARY); // 仅比较基础字母(忽略音调/大小写)collator.setStrength(Collator.SECONDARY); // 区分音调(如ā vs á)collator.setStrength(Collator.TERTIARY); // 全区分(默认,包括大小写)
中文场景建议:PRIMARY(拼音首字母)或SECONDARY(完整拼音)
4. 性能优化技巧
// 复用Collator实例(线程不安全,需配合ThreadLocal)
private static final ThreadLocal<Collator> COLLATOR =ThreadLocal.withInitial(() -> Collator.getInstance(Locale.CHINA));
5、生产环境增强建议
多音字处理
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); // 处理"重庆"等多音字
混合语言排序// 中英文混合排序策略
Comparator<CurrentStoreAllUsersDTO> comparator = (o1, o2) -> {if (isChinese(o1.getName()) && isChinese(o2.getName())) {return collator.compare(o1.getName(), o2.getName());}return o1.getName().compareTo(o2.getName());
};
扩展排序规则
// 先按部门排序,再按姓名拼音排序
Comparator.comparing(CurrentStoreAllUsersDTO::getDept).thenComparing(dto -> dto.getShiftExchangeUserName(), collator)
6、其他方案
(1)Pinyin4j
可获取拼音首字母,定制性强
需引入第三方库,多音字处理复杂
(2)数据库排序
性能高,利用索引
依赖数据库配置,灵活性差
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
实现
新建业务测试实体类
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;@Data
@Builder
@Accessors(chain = true)
public class CurrentStoreAllUsersDTO {private String shiftExchangeUserId;private String shiftExchangeUserName;}
新建排序方法
/*** 按中文姓名拼音升序排序(A-Z)* @param list 待排序的DTO列表* @return 排序后的新列表*/public static List<CurrentStoreAllUsersDTO> sortByNameChineseAZ(List<CurrentStoreAllUsersDTO> list) {Collator collator = Collator.getInstance(Locale.CHINA); // 中文拼音比较器//排序强度控制collator.setStrength(Collator.PRIMARY); // 忽略音调差异collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); // 处理多音字return Optional.ofNullable(list).orElseGet(ArrayList::new).stream().filter(Objects::nonNull).filter(dto -> StringUtils.isNotBlank(dto.getShiftExchangeUserName())).sorted(Comparator.comparing(dto -> StringUtils.defaultIfEmpty(dto.getShiftExchangeUserName(), ""),collator)).collect(Collectors.toList());}
调用示例
//测试数据List<CurrentStoreAllUsersDTO> users = List.of(CurrentStoreAllUsersDTO.builder().shiftExchangeUserName("张三姨").build(),CurrentStoreAllUsersDTO.builder().shiftExchangeUserName("李四姨").build(),CurrentStoreAllUsersDTO.builder().shiftExchangeUserName("王五姨").build(),CurrentStoreAllUsersDTO.builder().shiftExchangeUserName("阿姨").build(),CurrentStoreAllUsersDTO.builder().shiftExchangeUserName("").build(),CurrentStoreAllUsersDTO.builder().build());List<CurrentStoreAllUsersDTO> currentStoreAllUsersDTOS1 = sortByNameChineseAZ(users);System.out.println(currentStoreAllUsersDTOS1);
关键部分讲解
1、Optional.ofNullable(list).orElseGet(ArrayList::new)
防御式编程:通过Optional处理输入list为null的情况
惰性初始化:orElseGet比orElse更高效(避免不必要的对象创建)
等效传统写法
if (list == null) {list = new ArrayList<>();
}
2. 数据清洗层
.filter(Objects::nonNull)
.filter(dto -> StringUtils.isNotBlank(dto.getShiftExchangeUserName()))
3、核心排序层
.sorted(Comparator.comparing(dto -> StringUtils.defaultIfEmpty(dto.getShiftExchangeUserName(), ""),collator))
字段提取:通过Lambda表达式获取DTO中的用户名
空名字段处理:StringUtils.defaultIfEmpty 将null或空字符串转为""(避免NPE)
中文排序:Collator实例实现拼音序比较(比String.compareTo 更符合中文习惯)
注意这里的StringUtils是import org.apache.commons.lang3.StringUtils;
