2019-04-11

自然排序和Java中的實(shí)現(xiàn)

今天工作中突然遇到一個(gè)需求,需要對(duì)一個(gè)數(shù)據(jù)集合進(jìn)行排序罐栈,排序的依據(jù)是一個(gè)字符串字段豪嗽,由于這個(gè)數(shù)據(jù)集合是利用sql在MySQL中查找的結(jié)果,所以很自然而然的想到使用order by語(yǔ)句進(jìn)行排序

SELECT column1,column2,column3,...
FROM table
WHERE cases
ORDER BY need_sorted_field

正好這種排序結(jié)果也滿(mǎn)足了客戶(hù)的需求冕象,所以這個(gè)需求也是順利完成
但是事情遠(yuǎn)沒(méi)有那么簡(jiǎn)單代承。。渐扮。
這種排序機(jī)制是建立在字符串的格式完全一致的情況下的论悴,如果不一致,就會(huì)出現(xiàn)意想不到的結(jié)果墓律,于是我果斷查找了資料膀估,發(fā)現(xiàn)order by子句的排序算法使用的其實(shí)是自然排序(也稱(chēng)字典排序)

自然排序

copy by wiki~~

設(shè)想一本英語(yǔ)字典里的單詞,哪個(gè)在前哪個(gè)在后耻讽?
顯然的做法是先按照第一個(gè)字母察纯、以 a、b针肥、c……z 的順序排列饼记;如果第一個(gè)字母一樣,那么比較第二個(gè)慰枕、第三個(gè)乃至后面的字母具则。如果比到最后兩個(gè)單詞不一樣長(zhǎng)(比如,sigh 和 sight)捺僻,那么把短者排在前乡洼。

不難理解,order by子句就是把要排序的列當(dāng)成我們平時(shí)使用的字典匕坯,然后像字典那樣去排序

Java中的實(shí)現(xiàn)

Java提供了Comparable接口提供給開(kāi)發(fā)者自定義排序策略

public interface Comparable<T> {
    public int compareTo(T o);
}

幸運(yùn)的是束昵,Java針對(duì)字符串也繼承了該接口

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence

并且提供了簡(jiǎn)單的排序算法

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

其實(shí)不難發(fā)現(xiàn),這種比較策略大致和sql中的order by的比較策略是基本一樣的葛峻,因此锹雏,以后再面對(duì)相同的需求的時(shí)候,可以考慮直接使用String類(lèi)中的排序策略進(jìn)行排序
除此以外术奖,Java還提供了一種忽略大小寫(xiě)的字符串排序方式礁遵,也是實(shí)現(xiàn)在String類(lèi)中

/**
     * A Comparator that orders {@code String} objects as by
     * {@code compareToIgnoreCase}. This comparator is serializable.
     * <p>
     * Note that this Comparator does <em>not</em> take locale into account,
     * and will result in an unsatisfactory ordering for certain locales.
     * The java.text package provides <em>Collators</em> to allow
     * locale-sensitive ordering.
     *
     * @see     java.text.Collator#compare(String, String)
     * @since   1.2
     */
    public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();
    private static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
        // use serialVersionUID from JDK 1.2.2 for interoperability
        private static final long serialVersionUID = 8575799808933029326L;

        public int compare(String s1, String s2) {
            int n1 = s1.length();
            int n2 = s2.length();
            int min = Math.min(n1, n2);
            for (int i = 0; i < min; i++) {
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if (c1 != c2) {
                    c1 = Character.toUpperCase(c1);
                    c2 = Character.toUpperCase(c2);
                    if (c1 != c2) {
                        c1 = Character.toLowerCase(c1);
                        c2 = Character.toLowerCase(c2);
                        if (c1 != c2) {
                            // No overflow because of numeric promotion
                            return c1 - c2;
                        }
                    }
                }
            }
            return n1 - n2;
        }

        /** Replaces the de-serialized object. */
        private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
    }

調(diào)用方式很簡(jiǎn)單

String.CASE_INSENSITIVE_ORDER.compare(str1,str2);//str1和str2為對(duì)應(yīng)的字符串

其實(shí)不難發(fā)現(xiàn),這種方式就是在原來(lái)的compareTo方法里將字符都轉(zhuǎn)成了大寫(xiě)

參考文獻(xiàn)
字典序 by wiki

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末采记,一起剝皮案震驚了整個(gè)濱河市佣耐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唧龄,老刑警劉巖兼砖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡讽挟,警方通過(guò)查閱死者的電腦和手機(jī)懒叛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)耽梅,“玉大人薛窥,你說(shuō)我怎么就攤上這事⊙劢悖” “怎么了诅迷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)众旗。 經(jīng)常有香客問(wèn)我竟贯,道長(zhǎng),這世上最難降的妖魔是什么逝钥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮拱镐,結(jié)果婚禮上艘款,老公的妹妹穿的比我還像新娘。我一直安慰自己沃琅,他們只是感情好哗咆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著益眉,像睡著了一般晌柬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郭脂,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天年碘,我揣著相機(jī)與錄音,去河邊找鬼展鸡。 笑死屿衅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莹弊。 我是一名探鬼主播涤久,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼忍弛!你這毒婦竟也來(lái)了响迂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤细疚,失蹤者是張志新(化名)和其女友劉穎蔗彤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幕与,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年挑势,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啦鸣。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡潮饱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诫给,到底是詐尸還是另有隱情香拉,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布中狂,位于F島的核電站凫碌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胃榕。R本人自食惡果不足惜盛险,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望勋又。 院中可真熱鬧苦掘,春花似錦、人聲如沸楔壤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蹲嚣。三九已至递瑰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間隙畜,已是汗流浹背抖部。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留议惰,地道東北人您朽。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像换淆,于是被迫代替她去往敵國(guó)和親哗总。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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

  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí)倍试,會(huì)觸發(fā)此異常讯屈。 O...
    我想起個(gè)好名字閱讀 5,317評(píng)論 0 9
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,728評(píng)論 0 44
  • 數(shù)組 要求 實(shí)現(xiàn)一個(gè)支持動(dòng)態(tài)擴(kuò)容的數(shù)組 實(shí)現(xiàn)一個(gè)大小固定的有序數(shù)組,支持動(dòng)態(tài)增刪改操作 實(shí)現(xiàn)兩個(gè)有序數(shù)組合并為一個(gè)...
    小爆爆就是我閱讀 242評(píng)論 0 0
  • 昨天接近午餐時(shí)間辦公室同事一致推薦曉奇去買(mǎi)一份涼菜滿(mǎn)足一下無(wú)辣不歡的胃县习,沒(méi)承想曉奇推三阻四的不想去涮母。無(wú)巧不成書(shū)...
    守望幸福_a029閱讀 489評(píng)論 2 4
  • 每一個(gè)優(yōu)秀的人谆趾,都不是帶著與生俱來(lái)的光環(huán)的,也不一定是比別人幸運(yùn)叛本。他們只是在任何一件小事上沪蓬,都對(duì)自己有所...
    聞著墨香的清茶閱讀 167評(píng)論 1 4