<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java中List排序的3種方法!

          共 6387字,需瀏覽 13分鐘

           ·

          2021-12-26 00:01

          作者 | 王磊

          來源 | 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)行排序。

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

          1.使用 Comparable 排序

          按照本文設(shè)計的場景,我們需要創(chuàng)建一個包含了用戶列表的 List 集合,并按用戶的年齡從大到小進(jìn)行排序,具體實現(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 的實現(xiàn)方法有以下兩種:

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

          其中,第二種實現(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é)果,如下圖所示:本方法的核心實現(xiàn)代碼如下:

          2.2 匿名類比較器

          比較器 Comparator 可以使用更簡潔的匿名類的方式,來實現(xiàn)排序功能,具體實現(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 流來實現(xiàn)排序功能,它的實現(xiàn)只需要一行代碼,具體實現(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 有兩種實現(xiàn)的寫法,而在 JDK 8 之后的版本,就可以使用 Comparator.comparing 實現(xiàn)排序了,如果排序字段中可能出現(xiàn) null 值,要使用 Comparator.nullsXXX 進(jìn)行排序處理(否則會報錯)。

          卒然臨之而不驚,無故加之而不怒。享受平凡生活中的喜悅,終身成長者。

          博主:80 后程序員。

          愛好:讀書、寫作和慢跑。


          往期推薦

          面試官:如何實現(xiàn) List 集合去重?


          面試官:HashMap有幾種遍歷方法?推薦使用哪種?


          面試官:元素排序Comparable和Comparator有什么區(qū)別?


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级黄色片看看 | 亚洲性爱操逼大片 | 丁香五月婷婷中文字幕 | 看黄在线免费观看 | 国产精品性爱视频 |