Java 的 List.sort()
方法通过传入一个比较器(Comparator
),决定集合中元素的排列顺序。但 Java 默认的字符串比较并不能正确排序中文(尤其是按拼音顺序),这就需要使用 Collator
来实现符合中文语义的排序方式。
Java 默认使用 Unicode 编码值 进行字符串比较:
List<String> list = Arrays.asList("张三", "李四", "王五");
Collections.sort(list); // 默认排序方式
此时的排序结果可能是乱码或者无意义的顺序,因为它只是按字符的 Unicode 值排列。
java.text.Collator
是 Java 提供的 本地化字符串比较工具类,支持中文、日文、韩文等语言规则的比较。
使用 Collator 可以实现:
import java.text.Collator;
import java.util.*;
public class ChineseSortExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("张三", "李四", "王五");
Collator collator = Collator.getInstance(Locale.CHINA);
names.sort(collator); // 升序:拼音 A → Z
System.out.println(names);
}
}
list.sort((a, b) -> Collator.getInstance(Locale.CHINA).compare(a, b));
list.sort((a, b) -> Collator.getInstance(Locale.CHINA).compare(b, a));
✅ 记忆技巧:
compare(a, b)
表示“a 和 b 谁更小”,如果返回负数表示 a 更小,应该排前面;若返回正数表示 a 更大,应该排后面。
如果你有如下对象:
class Person {
private String name;
public String getName() { return name; }
}
你可以按 name
字段排序:
list.sort((o1, o2) ->
Collator.getInstance(Locale.CHINA).compare(o1.getName(), o2.getName()));
list.sort((o1, o2) ->
Collator.getInstance(Locale.CHINA).compare(o2.getName(), o1.getName()));
如果你想先按姓名拼音降序,再按时间升序,可以这样写:
list.sort((o1, o2) -> {
Collator collator = Collator.getInstance(Locale.CHINA);
int nameCompare = collator.compare(o2.getName(), o1.getName()); // 姓名降序
if (nameCompare != 0) return nameCompare;
return o1.getCreateTime().compareTo(o2.getCreateTime()); // 时间升序
});
方式 | 写法 | 效果 |
---|---|---|
默认排序 | Collections.sort(list) |
按 Unicode 排序,中文不正确 |
拼音升序 | compare(a, b) |
拼音 A → Z |
拼音降序 | compare(b, a) |
拼音 Z → A |
对象字段升序 | compare(o1.getField(), o2.getField()) |
自定义字段排序 |
对象字段降序 | compare(o2.getField(), o1.getField()) |
字段降序 |
多字段组合 | 使用 if (result != 0) 判断后继续比较第二字段 |
多条件排序 |
import java.text.Collator;
import java.util.*;
class User {
private String commitUser;
private Date commitTime;
public User(String commitUser, Date commitTime) {
this.commitUser = commitUser;
this.commitTime = commitTime;
}
public String getCommitUser() { return commitUser; }
public Date getCommitTime() { return commitTime; }
@Override
public String toString() {
return commitUser + " - " + commitTime;
}
}
public class ChineseSort {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("李四", new Date(100000)));
users.add(new User("王五", new Date(50000)));
users.add(new User("陈七", new Date(150000)));
users.sort((o1, o2) -> {
Collator collator = Collator.getInstance(Locale.CHINA);
int nameCmp = collator.compare(o2.getCommitUser(), o1.getCommitUser()); // 名字降序
if (nameCmp != 0) return nameCmp;
return o1.getCommitTime().compareTo(o2.getCommitTime()); // 时间升序
});
users.forEach(System.out::println);
}
}