按 unicode 码点值字典序排序,非拼音或自然数排序;逐字符比较码点差值,短串优先,故"file10.txt"排在"file2.txt"前。

直接用 String.compareTo() 对文件名列表排序,本质是按 Unicode 码点值逐字符比较,不是按“中文拼音”或“自然数识别”排序,所以会出现 "file10.txt" 排在 "file2.txt" 前面这类不符合直觉的结果。
字典序排序的实际执行过程
compareTo() 从左到右逐个比较两个字符串对应位置的字符,一旦遇到不相等的字符,就返回它们 Unicode 码点的差值(int 类型),不再看后续字符。如果所有对应字符都相同,较短的字符串排在前面;完全相等则返回 0。
-
"abc".compareTo("abd")→ 比较到第 3 位:'c'(99) vs 'd'(100) → 返回 -1 -
"abc".compareTo("abcd")→ 前 3 位相同,"abc" 更短 → 返回 -1 -
"File.txt".compareTo("file.txt")→ 'F'(70) vs 'f'(102) → 返回 -32(大写字母码点远小于小写)
常见字符的 Unicode 权重顺序(从小到大)
理解排序结果的关键,是记住常用字符在 Unicode 表中的大致位置:
- ASCII 控制符(0–31)、空格(32)
- 标点与数字:
'0'(48)到'9'(57) - 大写字母:
'A'(65)到'Z'(90) - 小写字母:
'a'(97)到'z'(122) - 中文汉字:基本在
\u4e00(一)到\u9fff(龿)之间,远大于英文字母
因此排序时:"1.txt" "A.txt" "a.txt" "你好.txt" —— 这是纯码点决定的,和语言习惯无关。
对文件名做“更合理”的排序(非默认字典序)
若想让 "file2.txt" 排在 "file10.txt" 前面,或忽略大小写、跳过前缀符号,需自定义 Comparator:
-
自然排序(Natural Order):用正则提取数字并转为整数比较,如 Apache Commons Lang 的
NaturalOrderComparator,或手写逻辑分离数字/非数字段 -
忽略大小写:用
String.CASE_INSENSITIVE_ORDER,或String::compareToIgnoreCase -
只比文件名主体(不含扩展名):先用
lastIndexOf('.')切分,再对 name 部分比较 -
中文按拼音排序:需引入
java.text.Collator,设置Collator.getInstance(Locale.CHINA)
实际排序代码示例
默认字典序(区分大小写、纯码点):
list.sort(String::compareTo); // 或 list.sort(Comparator.naturalOrder())
忽略大小写:
list.sort(String::compareToIgnoreCase); // 或 list.sort(String.CASE_INSENSITIVE_ORDER)
按拼音排序(中文友好):
Collator collator = Collator.getInstance(Locale.CHINA); list.sort(collator::compare);
注意:Collator 比较比 compareTo 慢,大数据量慎用;且它仍会把数字当作字符处理("2"










