1. 程式人生 > >十七、實現Windows中的檔名排序

十七、實現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));
    }
}