国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java中的Comparable與Comparator

2019-11-06 07:31:55
字體:
來源:轉載
供稿:網友

1.Comparable

Comparable是排序接口。此接口強行對實現它的每個類的對象進行整體排序。這種排序被稱為類的自然排序,類的compareTo()方法被稱為它的自然比較方法。

如果一個類實現了Comparable接口,就意味著該類”支持排序”。實現此接口的對象列表(或數組)可以通過Collections.sort()(或Arrays.sort())進行自動排序。實現此接口的對象可以用作有序映射中的鍵(比如TreeMap中的鍵)或者有序集合中的元素(比如TreeSet中的元素),而無需指定比較器。

Comparable接口僅僅只包括一個compareTo(Object obj)函數,如下所示:

public interface Comparable<T>{ public int compareTo(T o);}

假設我們通過x.compareTo(y)來比較xy的大小。若該方法返回正整數,則意味著x > y;若該方法返回負整數,則意味著x < y;若該方法返回0,則意味著x == y

2.Comparator

Comparator是比較器接口。我們可以將Comparator傳遞給sort方法(比如Collections.sort()或者Arrays.sort()),從而對一個Collection實現精準排序。還可以通過Comparator來控制某些數據結構(比如TreeSet或者TreeMap)的順序。

也就是說,我們如果要控制某個類的次序,而該類本身不支持排序(即沒有實現Comparable接口),那么我們就可以建立一個“該類的比較器”來進行排序。這個“比較器”只需要實現Comparator接口即可。

Comparator接口包括int compare(T o1,T o2)equals()兩個函數:

public interface Comparator<T>{ int compare(T o1, T o2); boolean equals(Object obj);}

要知道的是:

(1)若一個類實現了Comparator接口,它一定要實現compare(T o1,T o2)方法,但可以不實現equals(Object obj)方法。為什么呢?因為任何類都默認繼承于Object類,在Object類中實現了equals()方法,所以相當于其他所有的類都已經實現了equals()方法。(2)int compare(T o1,T o2)方法是比較o1o2的大小,該方法返回正整數,意味著o1o2大;返回負整數,意味著o1o2小;返回0,意味著o1o2相等。

3.Comparable與Comparator的比較

Comparable是排序接口;若一個類實現了Comparable接口,就意味著“該類支持排序” 而Comparator是比較器;我們若需要控制某個類的次序,可以建立一個“該類的比較器”來進行排序。

我們不難發現:Comparable相當于“內部比較器”,而Comparator相當于“外部比較器”。

下面我們舉一個例子。


首先我們自定義一個People類,如下:

public class People implements Comparable<People>{ PRivate String name; private int age; public String getName() { return name; } public int getAge() { return age; } public People(String name, int age) { super(); this.name = name; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } /** * 兩個People對象的name屬性和age屬性都相等,就認為兩個對象相等 */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; People other = (People) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return name + "---" + age; } /** * 默認的排序,按照name屬性排序 */ @Override public int compareTo(People o) { return this.name.compareTo(o.name); }}

People類有nameage兩個屬性,重寫了equals()hashCode()方法,并且重寫了toString()方法。最重要的是,People類實現了Comparable接口,并重寫了compareTo(People o)方法,該方法讓People類默認支持排序,并且排序的依據是name屬性的字母序。


接著,我們可以在主方法中測試:

public class Test { public static void main(String[] args) { System.out.println("----------ArrayList------------"); ArrayList<People> array = new ArrayList<>(); array.add(new People("ddd",20)); array.add(new People("aaa",30)); array.add(new People("ccc",10)); array.add(new People("bbb",40)); System.out.println("原始序列:"+array); // 對array進行排序,按照People類默認的排序方法,即按照name屬性進行升序排列 Collections.sort(array); System.out.println("Name升序:"+array); }}

程序輸出:

原始序列:[ddd---20, aaa---30, ccc---10, bbb---40]Name升序:[aaa---30, bbb---40, ccc---10, ddd---20]

可以看到,我們采用ArrayList保存了4個People類對象,并調用Collections.sotr()方法對該List進行排序,排序之前是原始序列;排序之后,按照People類中的定義,默認按照name屬性的升序排列。


除此之外,我們可以自定義Comparator類對象,使之按照age屬性進行排列。

比如,我們可以按照age屬性的升序排列:

public class AscAgeComparator implements Comparator<People> { @Override public int compare(People o1, People o2) { return o1.getAge() - o2.getAge(); }}

自定義AscAgeComparator類,實現Comparator接口,并重寫compare(People o1, People o2)方法,該方法按照age屬性進行升序排列。

或者我們也可以按照age屬性進行降序排列,如下定義DescAgeComparator:

public class DescAgeComparator implements Comparator<People> { @Override public int compare(People o1, People o2) { return o2.getAge() - o1.getAge(); }}

這時候我們在調用Collections.sort()方法時,也可以給該方法傳遞一個Comparator對象,使之按照該對象自定義的排序方式進行排序:

public class Test { public static void main(String[] args) { System.out.println("----------ArrayList------------"); ArrayList<People> array = new ArrayList<>(); array.add(new People("ddd",20)); array.add(new People("aaa",30)); array.add(new People("ccc",10)); array.add(new People("bbb",40)); System.out.println("原始序列:"+array); // 通過AscAgeComparator比較器進行排序,根據age升序排列 Collections.sort(array, new AscAgeComparator()); System.out.println("Age升序:"+array); // 通過DescAgeComparator比較器進行排序,根據age降序排列 Collections.sort(array, new DescAgeComparator()); System.out.println("Age降序:"+array); }}

程序輸出:

原始序列:[ddd---20, aaa---30, ccc---10, bbb---40]Age升序:[ccc---10, ddd---20, aaa---30, bbb---40]Age降序:[bbb---40, aaa---30, ddd---20, ccc---10]

4.Comparator的應用之實現Map按照value值進行排序

這里補充一個Comparator的一個很實用的應用例子。

Map本身并不支持按照value值進行排序,TreeMap實現的也是按照key值進行排序,那么如何實現Map按照value值進行排序呢?這時候我們可以將該Map轉換成List<Map.Entry<T,T>>,也就是把Map中每一個Entry鍵值對保存在List中,再自定義Comparator,對該List進行排序即可。

比如,我們再自定義People類如下:

public class People { private int age; private String name; public int getAge() { return age; } public String getName() { return name; } public People( String name,int age) { super(); this.age = age; this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; People other = (People) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return name + "---" + age; }}

這次,People類并沒有實現Comparable接口,也就是說People類不支持排序。

我們將People類對象作為value值保存在Map中,做如下測試:

public class Test { public static void main(String[] args) { HashMap<String, People> hm = new HashMap<>(); hm.put("1", new People("ddd",20)); hm.put("2", new People("ccc",40)); hm.put("3", new People("aaa",30)); hm.put("4", new People("bbb",10)); System.out.println("排序之前:"); hm.forEach((key,value) -> System.out.println(key + " " + value)); // 將Map中的每一個鍵值對轉化為Entry對象,保存在List中 List<Entry<String, People>> list = new ArrayList<>(hm.entrySet()); // 自定義Comparator,按照People對象的年齡升序進行排序 Comparator<Map.Entry<String, People>> valueComparator = new Comparator<Map.Entry<String,People>>() { @Override public int compare(Entry<String, People> o1, Entry<String, People> o2) { return o1.getValue().getAge() - o2.getValue().getAge(); } }; // 排序,比較器為我們自定義的valueComparator Collections.sort(list, valueComparator); System.out.println("排序之后:"); //java8中支持的遍歷輸出: list.forEach((item -> System.out.println(item.getKey() + " " + item.getValue()))); }}

最后我們按照People對象的age屬性進行升序排列,程序輸出:

排序之前:1 ddd---202 ccc---403 aaa---304 bbb---10排序之后:4 bbb---101 ddd---203 aaa---302 ccc---40
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 横山县| 镇宁| 东源县| 黎川县| 开平市| 潮州市| 苍山县| 达拉特旗| 深州市| 上杭县| 茶陵县| 南昌县| 社旗县| 赣州市| 浠水县| 湘潭县| 仪征市| 康平县| 策勒县| 灵宝市| 小金县| 五华县| 黎城县| 苍溪县| 时尚| 黄冈市| 邓州市| 江城| 土默特右旗| 安丘市| 乌兰县| 霍城县| 湄潭县| 无为县| 双鸭山市| 乌海市| 祥云县| 商水县| 仙桃市| 浦北县| 八宿县|