本文章有参考过其他博客文章,因当时没有保存下原博客链接,无法粘贴处原地址。


文件名排序问题

本文章主要使用了Comparator接口和compareTo(String anotherString)方法,详情可以参见javaApi文档。

  1. public interface Comparator

强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

  1. 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;
            }
        });
    }

如有待完善或不足的地方,欢迎留言或私信指出。
路漫漫其修远兮,吾将上下而求索。