所以,实际上你尝试通过它们的内容来比较行,也就是说,每一行都可以表示为一个字符串数组,其中一些字符串应该作为数字进行比较。
所以,自定义比较器需要根据上述要求这样实现:
- 数字应作为数字进行比较
- 字符串应该按字母顺序比较
- 数字在 个字符串之前(因此小于 个字符串)
private static int customCompare(String[] s1, String[] s2) {
int res = 0;
for (int i = 0, n = Math.min(s1.length, s2.length); res == 0 && i < n; i++) {
Comparable e1 = convert(s1[i]);
Comparable e2 = convert(s2[i]);
if (e1 instanceof Double && e2 instanceof Double) {
res = Double.compare((Double)e1, (Double)e2);
} else if (e1 instanceof String && e2 instanceof String) {
res = e1.compareTo(e2);
} else {
res = e1 instanceof Double ? -1 : 1;
}
}
return res != 0 ? res : Integer.compare(s1.length, s2.length);
}
// utility method to check for numeric format and convert to Double if needed
private static Comparable convert(String s) {
if (null == s || !s.matches("[-+]?(\\d+|\\d*\\.\\d+)")) {
return s;
}
return Double.valueOf(s);
}
测试:
String[] data = {
"-2.2\t2\t3\t4",
"2.2\t12345q\t69\t-afq",
"2.2\t12345q\t69\t-asdf",
"-22\t1234234\tasdfasf\tasdgas",
"-22\t-3\t4",
"",
"-1.1",
" ",
"qqqq\tq1.1",
"qqqq\t0.1",
"qqqq\t-1.1",
"-22\t11\tabc"
};
Arrays.stream(data)
.map(s -> s.split("\t")) // Stream<String[]> rows
.sorted(MyClass::customCompare) // reference to customCompare method
.map(arr -> String.join("\t", arr))
.forEach(System.out::println);
输出:
-22 -3 4
-22 11 abc
-22 1234234 asdfasf asdgas
-2.2 2 3 4
-1.1
2.2 12345q 69 -afq
2.2 12345q 69 -asdf
qqqq -1.1
qqqq 0.1
qqqq q1.1