面试官:说一下List排序方法
1. 前言
排序算是比較高頻的面試題了,節(jié)前面試了的兩家公司都有問(wèn)到排序問(wèn)題,整理后分享給大家(文末見(jiàn)總結(jié))。
通常我們想到實(shí)現(xiàn)排序就是 Collections 工具類的 sort() 方法,而 sort() 方法有兩種:
直接調(diào)用 Collections.sort(List list) 方法進(jìn)行排序(正序排序)。
調(diào)用 Collections.sort(List list,Comparator<? super T> c) ,自定義實(shí)現(xiàn) Comparator 接口,重新 compareTo 方法。(相當(dāng)于指定排序規(guī)則)
下面來(lái)詳細(xì)說(shuō)明這兩個(gè)方法。
2. 什么是 Comparator ?
在看方法之前,我們先來(lái)看看這個(gè) Comparator 到底有什么用?
Comparator ,中文意思為「比較器」,比較器的出現(xiàn)就是有些自定義類的 List 集合,不支持自身比較或者自身比較函數(shù)不能滿足需求時(shí),然后就可以寫一個(gè)比較器來(lái)完成兩個(gè)對(duì)象大小之間的比較,上邊提到的方法 2 就是指定使用自定義 Comparator 來(lái)實(shí)現(xiàn)比較;而方法 1 是不指定 Comparator,不指定就會(huì)使用默認(rèn)的排序方式(正序)。
3. List 屬性的不同
List 排序一般分為「單屬性排序」以及「實(shí)體屬性排序」,單屬性就是像是 String、Integer 等封裝類(List list,List list),這些基本類型的封裝類都已經(jīng)實(shí)現(xiàn)了 Comparable 接口,并重寫 compareTo() 方法,實(shí)體屬性則就是我們自定義的實(shí)體類,然后想通過(guò)某些屬性對(duì)象進(jìn)行排序。
單屬性
我們拿 Integer 類為例:
List<Integer> list = new ArrayList<Integer>();如下為 Integer 內(nèi)部的實(shí)現(xiàn)接口截圖:
所以,當(dāng)我們直接調(diào)用 Collections.sort() 方法就可以實(shí)現(xiàn)排序效果(正序),舉例說(shuō)明:
這就是單屬性集合的排序,直接調(diào)用 Collections.sort() 接口就能完成排序。
4. Comparable 和 Comparator 區(qū)別
然后就可能有小伙伴說(shuō),哎?你不對(duì)勁…
你上邊說(shuō)的是 Comparator 比較器,現(xiàn)在怎么 Integer 實(shí)現(xiàn)的是 Comparable 接口?Comparable 又是個(gè)什么鬼,這倆單詞怎么長(zhǎng)的這么像… 跟 Comparator 到底有啥區(qū)別呀?
咳咳,不要慌…
其實(shí)我們可以先看一下 Comparable 接口,該接口內(nèi)部就只有一個(gè) compareTo() 方法:
再來(lái)看看 Comparator 接口,Comparator 接口的內(nèi)部方法就比較多了,當(dāng)然,在這我們就關(guān)注一下 compare() 方法即可:
我們?cè)倩氐?Integer 類,Integer 實(shí)現(xiàn)了 Comparable 接口,所以我們找一下 compareTo() 方法如下:
如上方法,compareTo() 方法內(nèi)部調(diào)用了 Integer 內(nèi)部的 compare() 方法,通過(guò)注釋我們發(fā)現(xiàn)。
Integer 內(nèi)部完成了數(shù)值的比較?
其實(shí)到這也有點(diǎn)眉目了,好多文章有這么一個(gè)說(shuō)法:Comparable 屬于內(nèi)比較器,Comparator 屬于外比較器
所謂的內(nèi)比較器,我們還是以 Integer 為例,Integer 實(shí)現(xiàn)了 Comparable 接口,從 Integer 內(nèi)部完成了數(shù)值的比較,也就是拿另外一個(gè)值跟自身比。
所謂的外比較器,就是他會(huì)拿一個(gè)單獨(dú)的類來(lái)完成比較,這個(gè)時(shí)候我們就可以拿方法二來(lái)看了:
通過(guò)上面 List 的例子我們了解到了 Comparator 跟 Comparable 的使用,使用這兩種方式都可以完成單屬性的排序,區(qū)別就是內(nèi)外部實(shí)現(xiàn)不同。
排序規(guī)則:
o1大于o2,返回正整數(shù)
o1等于o2,返回0
o1小于o3,返回負(fù)整數(shù)
5. 實(shí)體屬性排序
因?yàn)槠綍r(shí)工作中還是以實(shí)體屬性 List 排序?yàn)橹?#xff0c;并不會(huì)是直接 List,所以下面我們就通過(guò)一個(gè) List 例子來(lái)分別通過(guò) Comparator、Comparable 實(shí)現(xiàn)排序。
User.java
public class User {/**用戶年齡**/private Integer age;public User(Integer age){this.age = age;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;} }5.1 Comparator 方式
代碼及執(zhí)行截圖:
5.2 Comparable 方式
我們需要讓 User.java 實(shí)體實(shí)現(xiàn)一個(gè) Comparable 接口,并重寫 compareTo() 方法:
public class User implements Comparable<User>{private Integer age;public User(Integer age){this.age = age;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic int compareTo(User o) {// return this.age - o.getAge(); 正序return o.getAge() - this.age; // 倒序} }然后我們測(cè)試一下:
ok,到這我們就實(shí)現(xiàn)了兩種方式完成對(duì)實(shí)體屬性對(duì)象的集合進(jìn)行排序。
6. 總結(jié)
實(shí)現(xiàn)排序有兩種方式:
-
對(duì)象內(nèi)部實(shí)現(xiàn) Comparable 接口,重新 compareTo() 方法(區(qū)分正序倒序),完成內(nèi)部比較,然后調(diào)用 Collections.sort() 排序。
-
新建一個(gè)實(shí)現(xiàn)了 Comparator 接口的類,并重寫 compare() 抽象方法
如下轉(zhuǎn)自:https://my.oschina.net/sdlvzg/blog/2243766
JDK1.8之后可以很方便的對(duì) List 進(jìn)行排序,不用再寫 Collections 類了。
6.1 基礎(chǔ)類型 List 排序
/* 對(duì)數(shù)字進(jìn)行排序 */ List<Integer> nums = Arrays.asList(3,1,5,2,9,8,4,10,6,7); nums.sort(Comparator.reverseOrder()); /* reverseOrder倒序 */ System.err.println("倒序:"+nums);nums.sort(Comparator.naturalOrder()); /* naturalOrder自然排序即:正序 */ System.err.println("正序:"+nums);執(zhí)行結(jié)果如下:
6.2 對(duì)象List單屬性排序
List<User> listDevs = new ArrayList<User>(){{add(new User(10));add(new User(9));add(new User(20));add(new User(4)); }};System.out.println("排序前:"); /*JAVA8的寫法,循環(huán)*/ listDevs.forEach((developer)->System.out.println(developer.getAge()));/*第一個(gè)寫法*/ Collections.sort(listDevs, new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return o1.getAge().compareTo(o2.getAge());} }); /*第二個(gè)寫法,JAVA8的寫法,List 接口支持直接使用 sort 該方法,不再需要使用 Collections.sort 了 listDevs.sort(listDevs, new Comparator<Developer>() {@Overridepublic int compare(Developer o1, Developer o2) {return o1.getAge().compareTo(o2.getAge();} });*//*第三個(gè)寫法,Lambda寫法,JAVA8的寫法 listDevs.sort((Developer o1, Developer o2)->o1.getAge().compareTo(o2.getAge()));*//*第四個(gè)寫法,Lambda寫法,JAVA8的寫法 listDevs.sort((o1, o2)->o1.getAge().compareTo(o2.getAge()));*//*第五寫法,個(gè)Lambda寫法,JAVA8的寫法 listDevs.sort(Comparator.comparing(Developer::getAge));*//*第六寫法,個(gè)Lambda寫法,JAVA8的寫法*/ Comparator<User> ageComparator = (o1, o2)->o1.getAge().compareTo(o2.getAge()); listDevs.sort(ageComparator); /*按上面配置的順序取值*/ listDevs.sort(ageComparator.reversed()); /*按上面配置的順序反向取值*/System.out.println("排序后:"); /*JAVA8的寫法,循環(huán)*/ listDevs.forEach((developer)->System.out.println(developer.getAge()));博客園持續(xù)更新:https://www.cnblogs.com/niceyoo
執(zhí)行截圖:
總結(jié)
以上是生活随笔為你收集整理的面试官:说一下List排序方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 那些对你说学历不重要,技术重要的人,他们
- 下一篇: 悦虎四代洛达1562M固件下载升级更新