java-sort

遇到一个排序需求,按照数字、字母、汉字的顺序排序。

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.ibm.icu/icu4j -->
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>4.8</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

Collections.sort(datas, new Comparator<TestVo>() {
@Override
public int compare(TestVo o1, TestVo o2) {
//
if (o1.getField1() == null) {
return 1;
} else if (o2.getField1() == null) {
return -1;
} else if (!o1.getField1().equals(o2.getField1())) {
return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField1(), o2.getField1());
}

//
if (o1.getField2() == null) {
return 1;
} else if (o2.getField2() == null) {
return -1;
}
if (!o1.getField2().equals(o2.getField2())) {
return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField2(), o2.getField2());
}

//
if (o1.getField3() == null) {
return 1;
} else if (o2.getField3() == null) {
return -1;
}
if (!o1.getField3().equals(o2.getField3())) {
return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o1.getField3(), o2.getField3());
}

//
if (o1.geField4() == null) {
return -1;
} else if (o2.geField4() == null) {
return 1;
}
if (!o1.geField4().equals(o2.geField4())) {
return com.ibm.icu.text.Collator.getInstance(com.ibm.icu.util.ULocale.SIMPLIFIED_CHINESE).compare(o2.geField4(), o1.geField4());
}

return 0;
}
});
1
2
3
4
5
6
7
8
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:777) ~[?:1.8.0_71]
at java.util.TimSort.mergeAt(TimSort.java:514) ~[?:1.8.0_71]
at java.util.TimSort.mergeCollapse(TimSort.java:439) ~[?:1.8.0_71]
at java.util.TimSort.sort(TimSort.java:245) ~[?:1.8.0_71]
at java.util.Arrays.sort(Arrays.java:1512) ~[?:1.8.0_71]
at java.util.ArrayList.sort(ArrayList.java:1454) ~[?:1.8.0_71]
at java.util.Collections.sort(Collections.java:175) ~[?:1.8.0_71]

JDK7中的Collections.Sort方法实现中,你的返回值需要严谨全面;
如果两个值是相等的,那么compare方法需要返回0,否则 可能 会在排序时抛错,而JDK6是没有这个限制的。
在在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性

说明:
1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同

文件排序

文件按日期排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Arrays.sort(files, new Comparator<File>() {
public int compare(File f1, File f2) {
long diff = f1.lastModified() - f2.lastModified();
if (diff > 0)
return 1;
else if (diff == 0)
return 0;
else
return -1;
}

public boolean equals(Object obj) {
return true;
}

});

按照文件名称排序

1
2
3
4
5
6
7
8
9
10
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (o1.isDirectory() && o2.isFile())
return -1;
if (o1.isFile() && o2.isDirectory())
return 1;
return o1.getName().compareTo(o2.getName());
}
});

按照文件大小排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Arrays.sort(files, new Comparator<File>() {
public int compare(File f1, File f2) {
long diff = f1.length() - f2.length();
if (diff > 0)
return 1;
else if (diff == 0)
return 0;
else
return -1;
}

public boolean equals(Object obj) {
return true;
}
});
1
String number = name.replaceAll("[^\\d]", "");

References

[1] Comparison method violates its general contract 问题的处理
[2] Comparison method violates its general contract!
[3] file.listFiles()按文件名称、日期、大小排序方法 总结
[4] file.listFiles()按文件大小、名称、日期排序方法