十七、实现Windows中的文件名排序

(一)普通JAVA排序和Windows排序的异同
  我们在使用File[] files = new File("E:\\demo\\novel").listFiles();从Windows中读取一个文件夹下的所有文件时,JDK会自动按照文件名进行排序,但是和Windows中的排序规则略有不同,如下:

1、Windows中的排序
在这里插入图片描述

2、JAVA中的排序

第189章 一直对你比较感兴趣.txt
第18章 想女人想疯了.txt
第190章 你二嫂,我老婆.txt
第191章 小三,狐狸精.txt
第192章 你也喜欢是不是.txt
第193章 二叔吃醋太惊悚.txt
第194章 小东西,这么着急.txt
第195章 岁月沉长,两情缠绵.txt
第196章 真的喜欢你.txt
第197章 爱惨了他.txt
第198章 一切有我,不用担心.txt
第199章 干一架痛快.txt
第19章 夏小玖真的是你吗.txt
第1章 火热的身体.txt
第200章 冲冠一怒为红颜.txt
第201章 米利竟然是它.txt
第202章 老子的女人你也敢碰.txt
第203章 学别人跟男人同居.txt
第204章 一起“锻炼身体”.txt

  从上面我们可以看出,对于 第1章 ,在Windows中是排在最前面的,而在Java中, 第1章 是排在所有以 1 开头的章节的最后面,比如 第10章第100章第1000章

  下面,我们就对排序进行一定的改造,实现仿windows对文件名进行排序。

(二)仿windows对文件名进行排序

  基本思想:将文件名作为一个字符串,依次遍历字符串中的每个字符进行比较,这里暂定待比较的字符串为 S1S2 ,使用Collator.getInstance(java.util.Locale.CHINA).compare(s1, s2)实现汉字、字母和数字大小的比较,比较规则如下:

  • 首先比较S1 和 S2 的长度,取最小长度
  • 然后按照最小长度,依次遍历字符串中的每个字符
    • 第一步:若取出的两个字符都是数字,则将数字保存到 StringBuffer 中,同时使用 continue 关键字,不执行后续逻辑,直接继续排序;
    • 第二步:当第一步执行完毕,判断若两个StringBuffer都非空
      • 1、若S1取出的字符还是数字,说明 类似于 第105章 和 第10章 这样的情况,则S1的排序应该在S2的后面,返回 1(大于1,则往后排);
      • 2、若S2取出的字符还是数字,则情况相反,返回 -1;
    • 第三步:若取出的两个字符不同时都是数字,则使用上面Collator.getInstance(java.util.Locale.CHINA).compare(s1, s2)进行比较,若返回值不是0,则两个字符不等,停止比较,返回比较结果;
    • 第四步:若经过最小长度比较,依然相等,则有两种情况:
      • 第一种:第10 第20,这种情况是S1和S2字符串长度相等,且两个StringBuffer都非空,则表明在取数字时并未进行比较久结束了,所以这里需要比较取出的值大小
      • 第二种:第10 第103,这种只需要比较两个字符串的长度,谁长谁排在后面

代码实现如下:

import java.text.Collator;
import java.util.*;

/**
 * @author 咸鱼
 * @date 2019/1/13 10:09
 */
public class SortUtil {
    public static void main(String[] args) {
        List<String> sortList = new ArrayList<>();
        sortList.add("第四");
        sortList.add("第20");
        sortList.add("第二");
        sortList.add("第3");
        sortList.add("第三");
        sortList.add("第10");
        sortList.add("第1088");
        //这是比较方法(可比较中文,但对于生僻字,效果不太好)
        Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA);
        sortList.sort((o1, o2) -> {
            //比较的基本原则,拿最小长度的字符串进行比较,若全部相等,则长字符串往后排
            int len1 = o1.length();
            int len2 = o2.length();
            int len = (len1 - len2) <= 0 ? len1 : len2;
            StringBuilder sb1 = new StringBuilder();
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < len; i++) {
                String s1 = o1.substring(i, i + 1);
                String s2 = o2.substring(i, i + 1);
                if (isNumeric(s1) && isNumeric(s2)){
                    //取出所有的数字
                    sb1.append(s1);
                    sb2.append(s2);
                    //取数字时,不比较
                    continue;
                }
                if (sb1.length() != 0 && sb2.length() != 0){
                    if (!isNumeric(s1) && !isNumeric(s2)){
                        int value1 = Integer.valueOf(sb1.toString());
                        int value2 = Integer.valueOf(sb2.toString());
                        return value1 - value2;
                    } else if (isNumeric(s1)) {
                        return 1;
                    } else if (isNumeric(s2)) {
                        return -1;
                    }
                }
                int result = CHINA_COMPARE.compare(s1, s2);
                if (result != 0) {
                    return result;
                }
            }
            //这一步:是为了防止以下情况:第10  第20,正好以数字结尾,且字符串长度相等
            if (len1 == len2 && sb1.length() != 0 && sb2.length() != 0) {
                int value1 = Integer.valueOf(sb1.toString());
                int value2 = Integer.valueOf(sb2.toString());
                return value1 - value2;
            }
            //若前面都相等,则直接比较字符串的长度,长的排后面,短的排前面
            return Integer.compare(len1, len2);
        });
    }
    //判断是否是数字
    private static boolean isNumeric(String s){
        return Character.isDigit(s.charAt(0));
    }
}

猜你喜欢

转载自blog.csdn.net/panchang199266/article/details/86420335