探究Java自然排序算法

natSort

說明

現(xiàn)實(shí)生活中有很多場景需要用到“自然排序”的算法翰蠢,比如對(duì)金錢表示的排序:“¥165.2橡卤,¥-365.03最盅,¥+0.80”驻右,還比如對(duì)日志文件名稱排序“version1.0.log什黑,version1.1.log1,version01.1.log2”等堪夭。這種情況下使用常規(guī)的字符串排序得到的結(jié)果是與實(shí)際業(yè)務(wù)不符合的愕把,即使查閱了一些第三方的開源框架,也沒有找到很好解決這個(gè)問題的方式(主要是業(yè)務(wù)性比較強(qiáng))森爽,所以不得已自己花了些時(shí)間寫了一個(gè)滿足“自然排序”算法恨豁。

代碼

/**
 * <自然排序算法>
 * <詳細(xì)介紹>
 *
 * @author Uncle陽zzZ
 * @since 設(shè)計(jì)wiki | 需求wiki
 */
public class NatSortComparator implements Comparator<Object> {

    private boolean careCase = false;

    private Pattern patternA;
    private Pattern patternB;


    /**
     * careCase
     * @param careCase
     */
    public NatSortComparator(boolean careCase)  {
        this.careCase = careCase;

        String pattern = "(-|\\+)?\\d+(.\\d+)?"; //^
        patternA = Pattern.compile(pattern);
        patternB = Pattern.compile(pattern);
    }

    /**
     * 比較算法
     * @param a
     * @param b
     * @return
     */
    @Override
    public int compare(Object a, Object b) {

        // simple compare
        if (a == b) {
            return 0;
        }

        if (a == null) {
            return -1;
        }

        if (b == null) {
            return 1;
        }

        if (a.equals(b)) {
            return 0;
        }

        String strA = a.toString();
        String strB = b.toString();

        Matcher matcherA = patternA.matcher(strA);
        Matcher matcherB = patternB.matcher(strB);

        Map<Integer, Integer> indexMapA = new HashMap<Integer, Integer>();
        Map<Integer, Integer> indexMapB = new HashMap<Integer, Integer>();

        while (matcherA.find()) {
            indexMapA.put(matcherA.start(), matcherA.end());
        }

        while (matcherB.find()) {
            indexMapB.put(matcherB.start(), matcherB.end());
        }

        int iA = 0;
        int iB = 0;


        while (true) {

            Character cA = getCharacter(strA, iA);
            Character cB = getCharacter(strB, iB);

            while (isSpaceChar(cA)) {
                cA = getCharacter(strA, ++iA);
            }

            while (isSpaceChar(cB)) {
                cB = getCharacter(strB, ++iB);
            }

            if (indexMapA.containsKey(iA) && indexMapB.containsKey(iB)) {
                String tempA = strA.substring(iA, indexMapA.get(iA));
                String tempB = strB.substring(iB, indexMapB.get(iB));

                int compareResult = Double.compare(Double.parseDouble(tempA), Double.parseDouble(tempB));
                if (compareResult != 0) {
                    return compareResult;
                }

                iA = indexMapA.get(iA);
                iB = indexMapB.get(iB);

                continue;
            }

            if (cA == null && cB == null) {
                return 0;
            }

            if (cA == null) {
                return -1;
            }

            if (cB == null) {
                return 1;
            }

            if (!careCase) {
                cA = Character.toUpperCase(cA);
                cB = Character.toUpperCase(cB);
            }

            int tempResult = cA.compareTo(cB);
            if (tempResult != 0) {
                return tempResult;
            }

            ++iA;
            ++iB;
        }
    }


    /**
     * 獲取字符
     * @param var
     * @param index
     * @return
     */
    private Character getCharacter(String var, int index) {
        if (var == null || index >= var.length()) {
            return null;
        }

        return var.charAt(index);
    }

    /**
     * 判斷是否是空格
     * @param var
     * @return
     */
    private boolean isSpaceChar(Character var) {
        return var != null && Character.isSpaceChar(var);
    }

}

問題

由于把‘-’號(hào)和‘+’號(hào)作為了數(shù)字匹配的因素之一,所以在應(yīng)對(duì)諸如時(shí)間格式如“2017-04-25”或者非數(shù)字語義的字符串如“中國-1個(gè)美麗的國度”時(shí),會(huì)出現(xiàn)排序結(jié)果非我所愿的情況∷獯椋看樣子直接通過某一算法來達(dá)到完全智能的排序是不可能的老玛,解決辦法可以針對(duì)不同的業(yè)務(wù)場景來裝配不同的比較器,或者用不同的Wrapper包裝對(duì)象達(dá)到期望的結(jié)果。

github:https://github.com/zhencygo/java/tree/master/algorithm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子象颖,更是在濱河造成了極大的恐慌,老刑警劉巖活箕,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件力麸,死亡現(xiàn)場離奇詭異可款,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)克蚂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門闺鲸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人埃叭,你說我怎么就攤上這事摸恍。” “怎么了赤屋?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵立镶,是天一觀的道長。 經(jīng)常有香客問我类早,道長媚媒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任涩僻,我火速辦了婚禮缭召,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逆日。我一直安慰自己嵌巷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布室抽。 她就那樣靜靜地躺著搪哪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坪圾。 梳的紋絲不亂的頭發(fā)上晓折,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音神年,去河邊找鬼已维。 笑死行嗤,一個(gè)胖子當(dāng)著我的面吹牛已日,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播栅屏,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼飘千,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了栈雳?” 一聲冷哼從身側(cè)響起护奈,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哥纫,沒想到半個(gè)月后霉旗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年厌秒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了读拆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸵闪,死狀恐怖檐晕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚌讼,我是刑警寧澤辟灰,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站篡石,受9級(jí)特大地震影響芥喇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凰萨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一乃坤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沟蔑,春花似錦湿诊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至食棕,卻和暖如春朗和,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背簿晓。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工眶拉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憔儿。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓忆植,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谒臼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子朝刊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容