本文章有参考过其他博客文章,因当时没有保存下原博客链接,无法粘贴处原地址。
文件名排序问题
本文章主要使用了Comparator接口和compareTo(String anotherString)方法,详情可以参见javaApi文档。
- public interface Comparator
强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
- public int compareTo(String anotherString)
按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。如果这两个字符串相等,则结果为 0;compareTo 只在方法 equals(Object) 返回 true 时才返回 0。
名称排序顺序:某些特殊字符<数字<字母<等等。。。
两个比较的排序的文字是: 3 s
比较结果值
0 相同不存入(不排序)
1 升序 (s 3)
-1 降序 (3 s)
例如:
//该list集合中值存放文件名称
List<String> list = new ArrayList<>();
list.add("312fsadradvqt41314hoif9we7592hf.jpg");
list.add("SDTR3R4353-314hoif9we7592hf.jpg");
//将上面的集合作为参数传入进去进行比较。
public void sortEvidenceAttch (List<String> list) {
Collections.sort(list, new Comparator<String>() {
protected List<String> split(String s) {
List<String> list = new ArrayList<String>();
char[] cs = s.toCharArray();
// 记录数字单元开头的索引位置
int tmp = -1;
for (int i = 0; i < cs.length; i++) {
char c = cs[i];
if (Character.isDigit(c)) {
if (tmp < 0) {
tmp = i;
}
} else {
if (tmp >= 0) {
// 将该字符之前的数字部分加入比较单元
list.add(s.substring(tmp, i));
tmp = -1;
}
list.add(String.valueOf(c));
}
}
// 如果最后一个是数字,将最后的数字加入list中
if (Character.isDigit(cs[cs.length - 1])) {
tmp = tmp < 0 ? cs.length - 1 : tmp;
list.add(s.substring(tmp, cs.length));
tmp = -1;
}
return list;
}
/**
*
* 比较各数字单元的长度
*
* @param s1
* @param s2
* @return
*/
private int compareNumberPart(String s1, String s2) {
int r = 0;
String[] ss1 = s1.split("\\D+");
String[] ss2 = s2.split("\\D+");
for (int i = 0; i < ss1.length; i++) {
r = compareValueEqualNumber(ss1[i], ss2[i]);
if (r != 0) {
return r;
}
}
return r;
}
/**
*
* 比较两个数字字符串表示的数字值的大小
*
* @param s1
* @param s2
* @return
*/
private int compareNumber(String s1, String s2) {
int max = String.valueOf((Integer.MAX_VALUE)).length() - 1;
int r = 0;
if (s1.length() > max || s2.length() > max) {
r = new BigInteger(s1).compareTo(new BigInteger(s2));
} else {
r = Integer.valueOf(s1).compareTo(Integer.valueOf(s2));
}
return r;
}
/**
*
* 比较数字相等的数字文本的大小,规则:位数较多者较小
*
* @param s1
* @param s2
* @return
*/
private int compareValueEqualNumber(String s1, String s2) {
int r = 0;
if (s1.length() > s2.length()) {
r = -1;
} else if (s1.length() < s2.length()) {
r = 1;
} else {
r = 0;
}
return r;
}
@Override
public int compare(EvidenceAttach evidenceAttach1, EvidenceAttach evidenceAttach2) {
// 省略提前判断和大小写转换部分的代码 详见附件
List<String> ss1 = split(evidenceAttach1.getAttName().toLowerCase());
List<String> ss2 = split(evidenceAttach2.getAttName().toLowerCase());
// 取两个比较单元的最小长度
int len = ss1.size() < ss2.size() ? ss1.size() : ss2.size();
// 比较结果
int r = 0;
// t1、t2 对应比较单元
String t1 = null;
String t2 = null;
// b1 b2 标识比较单元是否为数字
boolean b1 = false;
boolean b2 = false;
for (int i = 0; i < len; i++) {
t1 = ss1.get(i);
t2 = ss2.get(i);
b1 = Character.isDigit(t1.charAt(0));
b2 = Character.isDigit(t2.charAt(0));
// t1是数字 t2非数字
if (b1 && !b2) {
return -1;
}
// t2是数字 t1非数字
if (!b1 && b2) {
return 1;
}
// t1、t2 非数字
if (!b1 && !b2) {
r = t1.compareTo(t2);
if (r != 0) {
return r;
}
}
// t1 t2都是数字
if (b1 && b2) {
r = compareNumber(t1, t2);
if (r != 0) {
return r;
}
}
}
// 如果两个集合的 0-(len-1)部分相等
if (r == 0) {
if (ss1.size() > ss2.size()) {
r = 1;
} else if (ss1.size() < ss2.size()) {
r = -1;
} else {
r = compareNumberPart(evidenceAttach1.getAttName().toLowerCase(), evidenceAttach2.getAttName().toLowerCase());
}
}
return r;
}
});
}
如有待完善或不足的地方,欢迎留言或私信指出。
路漫漫其修远兮,吾将上下而求索。