1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Java中List排序的3種方法!

        共 6322字,需瀏覽 13分鐘

         ·

        2021-12-28 20:12

        作者 | 王磊

        來源 | Java中文社群(ID:javacn666)

        轉(zhuǎn)載請聯(lián)系授權(quán)(微信ID:GG_Stone)

        在某些特殊的場景下,我們需要在 Java 程序中對 List 集合進(jìn)行排序操作。比如從第三方接口中獲取所有用戶的列表,但列表默認(rèn)是以用戶編號從小到大進(jìn)行排序的,而我們的系統(tǒng)需要按照用戶的年齡從大到小進(jìn)行排序,這個時候,我們就需要對 List 集合進(jìn)行自定義排序操作了。

        List 排序的常見方法有以下 3 種:

        1. 使用 Comparable 進(jìn)行排序;
        2. 使用 Comparator 進(jìn)行排序;
        3. 如果是 JDK 8 以上的環(huán)境,也可以使用 Stream 流進(jìn)行排序。

        下面我們分別來看各種排序方法的具體實(shí)現(xiàn)。

        1.使用 Comparable 排序

        按照本文設(shè)計的場景,我們需要創(chuàng)建一個包含了用戶列表的 List 集合,并按用戶的年齡從大到小進(jìn)行排序,具體實(shí)現(xiàn)代碼如下:

        public?class?ListSortExample?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(1,?30,?"北京"));
        ????????????add(new?Person(2,?20,?"西安"));
        ????????????add(new?Person(3,?40,?"上海"));
        ????????}};
        ????????//?使用?Comparable?自定的規(guī)則進(jìn)行排序
        ????????Collections.sort(list);
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        }

        //??以下?set/get/toString?使用的是?lombok?的注解
        @Getter
        @Setter
        @ToString
        class?Person?implements?Comparable<Person>?{
        ????private?int?id;
        ????private?int?age;
        ????private?String?name;

        ????public?Person(int?id,?int?age,?String?name)?{
        ????????this.id?=?id;
        ????????this.age?=?age;
        ????????this.name?=?name;
        ????}

        ????@Override
        ????public?int?compareTo(Person?p)?{
        ????????return?p.getAge()?-?this.getAge();
        ????}
        }

        以上代碼的執(zhí)行結(jié)果,如下圖所示:本方法的核心代碼如下:

        2.使用 Comparator 排序

        Comparable 是類內(nèi)部的比較方法,而 Comparator 是排序類外部的比較器。使用 Comparator 比較器,無需修改原 Person 類,只需要擴(kuò)充一個 Person 類的比較器就行了,Comparator 的實(shí)現(xiàn)方法有以下兩種:

        • 新建 Comparator 比較器;
        • 使用 Comparator 匿名類比較器。

        其中,第二種實(shí)現(xiàn)方法要更簡潔一些,我們通過下面的具體代碼,來觀察一下二者的區(qū)別。

        2.1 新建 Comparator 比較器

        public?class?ListSortExample2?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(1,?30,?"北京"));
        ????????????add(new?Person(2,?20,?"西安"));
        ????????????add(new?Person(3,?40,?"上海"));
        ????????}};
        ????????//?使用?Comparator?比較器排序
        ????????Collections.sort(list,?new?PersonComparator());
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        }
        /**
        ?*?新建?Person?比較器
        ?*/

        class?PersonComparator?implements?Comparator<Person>?{
        ????@Override
        ????public?int?compare(Person?p1,?Person?p2)?{
        ????????return?p2.getAge()?-?p1.getAge();
        ????}
        }
        @Getter
        @Setter
        @ToString
        class?Person?{
        ????private?int?id;
        ????private?int?age;
        ????private?String?name;

        ????public?Person(int?id,?int?age,?String?name)?{
        ????????this.id?=?id;
        ????????this.age?=?age;
        ????????this.name?=?name;
        ????}
        }

        以上代碼的執(zhí)行結(jié)果,如下圖所示:本方法的核心實(shí)現(xiàn)代碼如下:

        2.2 匿名類比較器

        比較器 Comparator 可以使用更簡潔的匿名類的方式,來實(shí)現(xiàn)排序功能,具體實(shí)現(xiàn)代碼如下:

        public?class?ListSortExample2?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(1,?30,?"北京"));
        ????????????add(new?Person(2,?20,?"西安"));
        ????????????add(new?Person(3,?40,?"上海"));
        ????????}};
        ????????//?使用匿名比較器排序
        ????????Collections.sort(list,?new?Comparator()?{
        ????????????@Override
        ????????????public?int?compare(Person?p1,?Person?p2)?{
        ????????????????return?p2.getAge()?-?p1.getAge();
        ????????????}
        ????????});
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        }
        @Getter
        @Setter
        @ToString
        class?Person?{
        ????private?int?id;
        ????private?int?age;
        ????private?String?name;
        ????public?Person(int?id,?int?age,?String?name)?{
        ????????this.id?=?id;
        ????????this.age?=?age;
        ????????this.name?=?name;
        ????}
        }

        以上代碼的執(zhí)行結(jié)果,如下圖所示:

        3.使用 Stream 流排序

        在 JDK 8 之后可以使用更加簡單的方法 Stream 流來實(shí)現(xiàn)排序功能,它的實(shí)現(xiàn)只需要一行代碼,具體實(shí)現(xiàn)如下:

        public?class?ListSortExample3?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(1,?30,?"北京"));
        ????????????add(new?Person(2,?20,?"西安"));
        ????????????add(new?Person(3,?40,?"上海"));
        ????????}};
        ????????//?使用?Stream?排序
        ????????list?=?list.stream().sorted(Comparator.comparing(Person::getAge).reversed())
        ????????????????.collect(Collectors.toList());
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        ????@Getter
        ????@Setter
        ????@ToString
        ????static?class?Person?{
        ????????private?int?id;
        ????????private?int?age;
        ????????private?String?name;
        ????????public?Person(int?id,?int?age,?String?name)?{
        ????????????this.id?=?id;
        ????????????this.age?=?age;
        ????????????this.name?=?name;
        ????????}
        ????}
        }

        其中 reversed() 表示倒序的意思,如果不使用此方法則是正序。

        以上代碼的執(zhí)行結(jié)果,如下圖所示:

        擴(kuò)展:排序字段為 null

        使用 Stream 進(jìn)行排序時,如果排序的字段出現(xiàn) null 值就會導(dǎo)致異常發(fā)生,具體示例如下:

        public?class?ListSortExample4?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(30,?"北京"));
        ????????????add(new?Person(10,?"西安"));
        ????????????add(new?Person(40,?"上海"));
        ????????????add(new?Person(null,?"上海"));?//?年齡為?null?值
        ????????}};
        ????????//?按照[年齡]正序,但年齡中有一個?null?值
        ????????list?=?list.stream().sorted(Comparator.comparing(Person::getAge))
        ????????????????.collect(Collectors.toList());
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        }
        @Getter
        @Setter
        @ToString
        class?Person?{
        ????private?Integer?age;
        ????private?String?name;

        ????public?Person(Integer?age,?String?name)?{
        ????????this.age?=?age;
        ????????this.name?=?name;
        ????}
        }

        以上代碼的執(zhí)行結(jié)果,如下圖所示:想要解決上述問題,需要給 Comparator.comparing 傳遞第二個參數(shù):Comparator.nullsXXX,如下代碼所示:

        public?class?ListSortExample4?{
        ????public?static?void?main(String[]?args)?{
        ????????//?創(chuàng)建并初始化?List
        ????????List?list?=?new?ArrayList()?{{
        ????????????add(new?Person(30,?"北京"));
        ????????????add(new?Person(10,?"西安"));
        ????????????add(new?Person(40,?"上海"));
        ????????????add(new?Person(null,?"上海"));
        ????????}};
        ????????//?按照[年齡]正序,但年齡中有一個?null?值
        ????????list?=?list.stream().sorted(Comparator.comparing(Person::getAge,
        ????????????????Comparator.nullsFirst(Integer::compareTo)))
        ????????????????.collect(Collectors.toList());
        ????????//?打印?list?集合
        ????????list.forEach(p?->?{
        ????????????System.out.println(p);
        ????????});
        ????}
        }
        @Getter
        @Setter
        @ToString
        class?Person?{
        ????private?Integer?age;
        ????private?String?name;

        ????public?Person(Integer?age,?String?name)?{
        ????????this.age?=?age;
        ????????this.name?=?name;
        ????}
        }

        Comparator.nullsFirst 表示將排序字段中的 null 值放到集合最前面,如果想要將 null 值放到集合最后面可以使用 Comparator.nullsLast。

        以上代碼的執(zhí)行結(jié)果,如下圖所示:

        總結(jié)

        本文介紹了 3 種 List 排序的方法,前兩種方法常用于 JDK 8 之前的版本,其中比較器 Comparator 有兩種實(shí)現(xiàn)的寫法,而在 JDK 8 之后的版本,就可以使用 Comparator.comparing 實(shí)現(xiàn)排序了,如果排序字段中可能出現(xiàn) null 值,要使用 Comparator.nullsXXX 進(jìn)行排序處理(否則會報錯)。





        0、重磅!兩萬字長文總結(jié),梳理 Java 入門進(jìn)階哪些事(推薦收藏)

        1、30歲生日,總結(jié)過去的一年,我哭了……

        2、看完這設(shè)計模式匯總,你確定不加收藏嗎


        瀏覽 58
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            草草网 | 精品人妻一区二区三区在线浪潮 | 欧美三级视频网站 | 丁香五月婷婷啪啪 | 国产男人猛躁进女人的导演 | 日本特黄 AA片免费视频 | 豆花视频在线资源福利总站 | 国产日产欧美在线观看 | 国产3p又大又爽又粗又硬免费 | 国产欧美日韩另类 |