这次项目中碰到这样一个问题:对一个乱序的字符串集合进行排序,字符串集合包含以下内容
"1"、"1.1"、"1.3"、"1.9"、"1.7"、"1.10.1、"1.10"、"1.2"、"1.4"、"1.5"、"1.8"、"1.6"、"1.11"、"2.4"、"2.10"、"1.1.10"、
"1.1.8"、"2.1.3"、"2.1.5"、"2.1.10"
使用集合默认的排序功能,结果是这样的
"1"、"1.1"、"1.1.10"、"1.1.8"、"1.10"、"1.10.1"、"1.11"、"1.2"、"1.3"、"1.4"、"1.5"、"1.6"、"1.7"、"1.8"、"1.9"、
"2.1.10"、"2.1.3"、"2.1.5"、" 2.10"、"2.4"
可以看到"1.10"、"1.1.10"、"2.1.10"等字符串的排序是不符合预期的,所以我手动写了一个比较器解决该问题。
具体实现如下:
public class StringComparator implements Comparator<String> {
private final int ToRight = 1;
private final int ToLeft = -1;
@Override
public int compare(String str1, String str2) {
String[] str1Split = str1.split("\\.");
String[] str2Split = str2.split("\\.");
int minSplitLength = str1Split.length > str2Split.length
? str2Split.length : str1Split.length;
// 用长度小的数组长度作为遍历边界,防止数组越界
for (int i = 0; i < minSplitLength; i++) {
// 将字符串转换成数字解决 一位数字(eg: 2) 和 两位数字(eg: 10) 的大小比较问题
Integer strToInt1 = Integer.valueOf(str1Split[i]);
Integer strToInt2 = Integer.valueOf(str2Split[i]);
int compareResult = strToInt1.compareTo(strToInt2);
if (compareResult == 0) {
continue;
} else if (compareResult > 0) {
return ToRight;
} else if (compareResult < 0) {
return ToLeft;
}
}
// 若程序进行到这里,说明在循环里没有得出比较结果。
// 此时应该是数组长度长的字符串(1.10.1)排在后面,数组长度短的字符串(1.10)排在前面
if (minSplitLength == str1Split.length) {
return ToLeft;
} else {
return ToRight;
}
}
public static void main(String[] args) {
String[] dataSource = new String[] {"1","1.1","1.3","1.9","1.7","1.10.1","1.10",
"1.2","1.4","1.5", "1.8","1.6","1.11","2.4","2.10","1.1.10","1.1.8",
"2.1.3","2.1.5","2.1.10","2"};
List<String> data = new ArrayList<>(Arrays.asList(dataSource));
System.out.println("original data: " + data);
TreeSet<String> stringComparator = new TreeSet<>(new StringComparator());
// 数据排序
stringComparator.addAll(data);
// 将排序完成的数据放回原集合
data.clear();
data.addAll(stringComparator);
System.out.println("sorted data: " + data);
}
}
打印结果如下:
original data: [1, 1.1, 1.3, 1.9, 1.7, 1.10.1, 1.10, 1.2, 1.4, 1.5, 1.8, 1.6, 1.11, 2.4, 2.10, 1.1.10, 1.1.8, 2.1.3, 2.1.5, 2.1.10, 2]
sorted data: [1, 1.1, 1.1.8, 1.1.10, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.10.1, 1.11, 2, 2.1.3, 2.1.5, 2.1.10, 2.4, 2.10]