這是泥瓦匠的第103篇原創java
文章工程:
* JDK 1.8
* 工程名:algorithm-core-learning # StringComparisonDemo
* 工程地址:https://github.com/JeffLi1993/algorithm-core-learninggit
Q:什麼是選擇問題?
選擇問題,是假設一組 N 個數,要肯定其中第 K 個最大值者。好比 A 與 B 對象須要哪一個更大?又好比:要考慮從一些數組中找出最大項?github
解決選擇問題,須要對象有個能力,即比較任意兩個對象,並肯定哪一個大,哪一個小或者相等。找出最大項問題的解決方法,只要依次用對象的比較(Comparable)能力,循環對象列表,一次就能解決。算法
那麼 JDK 源碼如何實現比較(Comparable)能力的呢?spring
Comparable 接口,從 JDK 1.2 版本就有了,歷史算悠久。Comparable 接口強制了實現類對象列表的排序。其排序稱爲天然順序,其 compareTo
方法,稱爲天然比較法。數組
該接口只有一個方法 public int compareTo(T o);
,能夠看出springboot
對象的集合列表(Collection List)或者數組(arrays) ,也有對應的工具類能夠方便的使用:微信
那 String 對象如何被比較的?數據結構
String 源碼中能夠看到 String JDK 1.0 就有了。那麼應該是 JDK 1.2 的時候,String 類實現了 Comparable 接口,而且傳入須要被比較的對象是 String。對象如圖:socket
String 是一個 final 類,沒法從 String 擴展新的類。從 114 行,能夠看出字符串的存儲結構是字符(Char)數組。先能夠看看一個字符串比較案例,代碼以下:
/** * 字符串比較案例 * * Created by bysocket on 19/5/10. */ public class StringComparisonDemo { public static void main(String[] args) { String foo = "ABC"; // 前面和後面每一個字符徹底同樣,返回 0 String bar01 = "ABC"; System.out.println(foo.compareTo(bar01)); // 前面每一個字符徹底同樣,返回:後面就是字符串長度差 String bar02 = "ABCD"; String bar03 = "ABCDE"; System.out.println(foo.compareTo(bar02)); // -1 (前面相等,foo 長度小 1) System.out.println(foo.compareTo(bar03)); // -2 (前面相等,foo 長度小 2) // 前面每一個字符不徹底同樣,返回:出現不同的字符 ASCII 差 String bar04 = "ABD"; String bar05 = "aABCD"; System.out.println(foo.compareTo(bar04)); // -1 (foo 的 'C' 字符 ASCII 碼值爲 67,bar04 的 'D' 字符 ASCII 碼值爲 68。返回 67 - 68 = -1) System.out.println(foo.compareTo(bar05)); // -32 (foo 的 'A' 字符 ASCII 碼值爲 65,bar04 的 'a' 字符 ASCII 碼值爲 97。返回 65 - 97 = -32) String bysocket01 = "泥瓦匠"; String bysocket02 = "瓦匠"; System.out.println(bysocket01.compareTo(bysocket02));// -2049 (泥 和 瓦的 Unicode 差值) } }
運行結果以下:
0 -1 -2 -1 -32 -2049
能夠看出, compareTo
方法是按字典順序比較兩個字符串。具體比較規則能夠看代碼註釋。比較規則以下:
再看看 String 的 compareTo
方法如何實現字典順序的。源碼如圖:
源碼解析以下:
因此要排序,確定先有比較能力,即實現 Comparable 接口。而後實現此接口的對象列表(和數組)能夠經過 Collections.sort(和 Arrays.sort)進行排序。
還有 TreeSet 使用樹結構實現(紅黑樹),集合中的元素進行排序。其中排序就是實現 Comparable 此接口
另外,若是沒有實現 Comparable 接口,使用排序時,會拋出 java.lang.ClassCastException 異常。詳細看《Java 集合:3、HashSet,TreeSet 和 LinkedHashSet比較》https://www.bysocket.com/archives/195
上面也說到,這種比較其實有必定的弊端:
方法參數:定義一個沒有數據只有方法的類,並傳遞該類的實例。一個函數經過將其放在一個對象內部而被傳遞。這種對象一般叫作函數對象(Funtion Object)
在接口方法設計中, T execute(Callback callback) 參數中使用 callback 相似。好比在 Spring 源碼中,能夠看出不少設計是:聚合優先於繼承或者實現。這樣能夠減小不少繼承或者實現。相似 SpringJdbcTemplate 場景設計,能夠考慮到這種 Callback 設計實現。
本文示例讀者能夠經過查看下面倉庫的中: StringComparisonDemo 字符串比較案例案例:
若是您對這些感興趣,歡迎 star、follow、收藏、轉發給予支持!