好奇,我们常用的 Integer 内部为什么会去实现 Comparable 接口,他的作用是什么?...
作者:巫師大人
blog.csdn.net/ysj4428/article/details/81195846
今天在開發中無意看到Integer包裝類內部實現了Comparable接口,因此探查一下該接口作用:
查看API解釋:
此接口強行對實現它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的 compareTo 方法被稱為它的自然比較方法。
一、為什么需要實現這個接口呢?
首先看一下數據的例子:
String[]?strArr?=?{"A","B","C","E","D"}; Arrays.sort(strArr); for?(String?string?:?strArr)?{System.out.print(string+";"); }輸出結果:
A;B;C;D;E;從中我們可以看出sort方法對數據中的String字符串按照一定規則進行了排序,那為什么會排序呢?
查看String類我們可以看到:
public?final?class?String implements?Serializable,?Comparable,?CharSequence{... }它也實現了Comparable接口。里面實現了compareTo方法,所以按照某種規則能夠進行排序。
如果數組中的對象不是String而是自定義的類型呢?
public?class?ComparableDemo{public?static?void?main(String[]?args)?{Object[]?objArray?=?{new?Person(20,"jack"),new?Person(17,"tom"),new?Person(27,"aj")};for?(Object?object?:?objArray)?{System.out.print(object.toString());}Arrays.sort(objArray);for?(Object?object?:?objArray)?{System.out.print(object.toString());}} }public?class?Person?{private?Integer?age;private?String?name;public?Person(int?age,String?name)?{this.age?=?age;this.name?=?name;}@Overridepublic?String?toString()?{return?"Person?[age="?+?age?+?",?name="?+?name?+?"]";}}結果為:
Person?[age=20,?name=jack]Person?[age=17,?name=tom]Person?[age=27,?name=aj] Exception?in?thread?"main"?java.lang.ClassCastException:?interfacedemo.Person?cannot?be?cast?to?java.lang.Comparableat?java.util.ComparableTimSort.countRunAndMakeAscending(Unknown?Source)at?java.util.ComparableTimSort.sort(Unknown?Source)at?java.util.ComparableTimSort.sort(Unknown?Source)at?java.util.Arrays.sort(Unknown?Source)at?interfacedemo.ComparableDemo.main(ComparableDemo.java:18)可以看到不進行排序打印是正常的,但是排序時報錯了。因為系統無法知道使用什么規則進行排序。
我們存入字符串排序成功是因為String類已經實現Comparable接口,因此想要實現自定義對象比較同樣需要實現該接口,其中的比較方法規則由我們自己設定。Java知音公眾號內回復“后端面試”,送你一份Java面試題寶典
二、接口簡介
實現此接口的對象列表(和數組)可以通過 Collections.sort(和 Arrays.sort)進行自動排序。實現此接口的對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。
對于類 C 的每一個 e1 和 e2 來說,當且僅當 e1.compareTo(e2) == 0 與 e1.equals(e2) 具有相同的 boolean 值時,類 C 的自然排序才叫做與 equals 一致。注意,null 不是任何類的實例,即使 e.equals(null) 返回 false,e.compareTo(null) 也將拋出 NullPointerException。
建議(雖然不是必需的)最好使自然排序與 equals 一致。這是因為在使用自然排序與 equals 不一致的元素(或鍵)時,沒有顯式比較器的有序集合(和有序映射表)行為表現“怪異”。尤其是,這樣的有序集合(或有序映射表)違背了根據 equals 方法定義的集合(或映射表)的常規協定。
例如,如果將兩個鍵 a 和 b 添加到沒有使用顯式比較器的有序集合中,使 (!a.equals(b) && a.compareTo(b) == 0),那么第二個 add 操作將返回 false(有序集合的大小沒有增加),因為從有序集合的角度來看,a 和 b 是相等的。
實際上,所有實現 Comparable 的 Java 核心類都具有與 equals 一致的自然排序。java.math.BigDecimal 是個例外,它的自然排序將值相等但精確度不同的 BigDecimal 對象(比如 4.0 和 4.00)視為相等。
從數學上講,定義給定類 C 上自然排序的關系式 如下:
{(x, y)|x.compareTo(y)?<=?0}。整體排序的 商 是:
{(x, y)|x.compareTo(y)?==?0}。它直接遵循 compareTo 的協定,商是 C 的 等價關系,自然排序是 C 的 整體排序。當說到類的自然排序 與 equals 一致 時,是指自然排序的商是由類的 equals(Object) 方法定義的等價關系。
{(x, y)|x.equals(y)}。此接口是 Java Collections Framework 的成員。Java知音公眾號內回復“后端面試”,送你一份Java面試題寶典
三、實現該接口
上面的例子進行修改,這里通過比較對象中的age屬性進行排序
public?class?Person?implements?Comparable{private?Integer?age;private?String?name;public?Person(int?age,String?name)?{this.age?=?age;this.name?=?name;}@Overridepublic?String?toString()?{return?"Person?[age="?+?age?+?",?name="?+?name?+?"]";}//進行方法重寫@Overridepublic?int?compareTo(Object?o)?{Person?p?=?(Person)o;return?this.age?-?p.age;}}結果打印:
Person?[age=20,?name=jack]Person?[age=17,?name=tom]Person?[age=27,?name=aj] Person?[age=17,?name=tom]Person?[age=20,?name=jack]Person?[age=27,?name=aj]最后附上該方法API描述:
compareTo
int?compareTo(T?o)比較此對象與指定對象的順序。如果該對象小于、等于或大于指定對象,則分別返回負整數、零或正整數。
實現類必須確保對于所有的 x 和 y 都存在 sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) 的關系。(這意味著如果 y.compareTo(x) 拋出一個異常,則 x.compareTo(y) 也要拋出一個異常。)
實現類還必須確保關系是可傳遞的:(x.compareTo(y)>0 && y.compareTo(z)>0) 意味著 x.compareTo(z)>0。
最后,實現者必須確保 x.compareTo(y)==0 意味著對于所有的 z,都存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。強烈推薦 (x.compareTo(y)==0) == (x.equals(y)) 這種做法,但并不是 嚴格要求這樣做。一般來說,任何實現 Comparable 接口和違背此條件的類都應該清楚地指出這一事實。推薦如此闡述:“注意:此類具有與 equals 不一致的自然排序。”
在前面的描述中,符號 sgn(expression) 指定 signum 數學函數,該函數根據 expression 的值是負數、零還是正數,分別返回 -1、0 或 1 中的一個值。
參數:
o - 要比較的對象。
返回:
負整數、零或正整數,根據此對象是小于、等于還是大于指定對象。
拋出:
ClassCastException - 如果指定對象的類型不允許它與此對象進行比較。
推薦文章今天給大家推薦6個Spring Boot項目,拿來就可以賺錢!
分享一套基于SpringBoot和Vue的企業級中后臺開源項目,這個項目有點哇塞!
圈子哥推薦一種基于Spring Boot開發OA開源產品,學習/搞外快都是不二選擇!
硬剛一周,3W字總結,一年的經驗告訴你如何準備校招!
總結
以上是生活随笔為你收集整理的好奇,我们常用的 Integer 内部为什么会去实现 Comparable 接口,他的作用是什么?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再见,微服务!
- 下一篇: MyBatis动态SQL,写SQL更爽