【java】Comparator的用法


文章轉載自: http://blog.csdn.net/u012250875/article/details/55126531

1.為什么寫?

  1. comparator 是javase中的接口,位於java.util包下,javase中的所有接口抽象度都很高,有必要重視
  2. 網上太多的文章告訴大家comparator是用來排序;確實,可以用來排序,但不僅限於排序
  3. 工作中實際需求出現很多需要使用comparator去處理的問題,在此總結一下。

2.接口功能

該接口的功能表示一個比較器,比較器當然具有可比性!那為什么一百度全是說是用來排序的?這是因為數組工具類和集合工具類中提供的工具方法sort方法都給出了含有Comparator接口的重載方法,大家見久了都只想到Comparator接口是用來排序的,按照java抽象的尿性來看,該接口如果為排序而生,我估計應該叫類似Sortable,Sortor之類的名字吧!下面是javase中該接口的使用原型:

1 Arrays.sort(T[],Comparator<? super T> c);
2 Collections.sort(List<T> list,Comparator<? super T> c);

 

3.使用場景

考慮什么場景使用該接口就需要考慮什么時候需要比較,比較常用的場景:
1. 排序需要比較,需要比較兩個對象誰在前誰在后。
2. 分組需要比較,需要比較兩個對象是否是屬於同一組。
3. 待補充

4.舉個栗子

1.排序
在List或數組中的對象如果沒有實現Comparable接口時,那么就需要調用者為需要排序的數組或List設置一個Compartor,Compartor的compare方法用來告訴代碼應該怎么去比較兩個實例,然后根據比較結果進行排序

talk is cheap show me the code

 1 package com.java.demo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collections;
 5 import java.util.Comparator;
 6 import java.util.List;
 7 /**
 8  * @author puyf
 9  */
10 public class SortTest {
11     class Dog{
12     public int age;
13     public String name;
14     public Dog(int age, String name) {
15         super();
16         this.age = age;
17         this.name = name;
18     }
19     @Override
20     public String toString() {
21         return "Dog [age=" + age + ", name=" + name + "]";
22     }
23     }
24     public static void main(String[] args) {
25     List<Dog> list= new ArrayList<>();
26     list.add(new SortTest().new Dog(5, "DogA"));
27     list.add(new SortTest().new Dog(6, "DogB"));
28     list.add(new SortTest().new Dog(7, "DogC"));
29     Collections.sort(list, new Comparator<Dog>() {
30 
31         @Override
32         public int compare(Dog o1, Dog o2) {
33         return o2.age - o1.age;
34         }
35     });
36     System.out.println("給狗狗按照年齡倒序:"+list);
37     Collections.sort(list, new Comparator<Dog>() {
38 
39         @Override
40         public int compare(Dog o1, Dog o2) {
41         return o1.name.compareTo(o2.name);
42         }
43     });
44     System.out.println("給狗狗按名字字母順序排序:"+list);
45     }
46 }

 

2.分組
使用Comparator和for循環處理列表,來進行分類;通過調用者實現Comparator接口的比較邏輯,來告訴程序應該怎么比較,通過比較之后得結果來進行分組。比如生活中的拳擊比賽,會有公斤級的概念,那么程序中應該實現的處理邏輯是只要兩個人的體重在同一個區間則為同一組公斤級的選手。下面例子中分別按照狗狗的顏色和體重級別兩個維度來進行分組,因此分組的核心邏輯其實就是比較邏輯。相面我抽了一個工具方法:dividerList,第一個參數為需要處理的數據源,第二參數是分組時的比較邏輯。

 1 package com.java.demo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Comparator;
 5 import java.util.List;
 6 /**
 7  * @author puyf
 8  */
 9 public class GroupTest {
10     class Apple {
11     public String color;
12     public int weight;
13 
14     public Apple(String color, int weight) {
15         super();
16         this.color = color;
17         this.weight = weight;
18     }
19 
20     @Override
21     public String toString() {
22         return "Apple [color=" + color + ", weight=" + weight + "]";
23     }
24     }
25 
26     /**
27      * @param list 
28      * @param comparator 比較是否為同一組的比較器
29      * @return
30      */
31     public static <T> List<List<T>> dividerList(List<T> list,Comparator<? super T> comparator) {
32     List<List<T>> lists = new ArrayList<>();
33     for (int i = 0; i < list.size(); i++) {
34         boolean isContain = false;
35         for (int j = 0; j < lists.size(); j++) {
36         if (lists.get(j).size() == 0
37             ||comparator.compare(lists.get(j).get(0),     list.get(i)) == 0) {
38             lists.get(j).add(list.get(i));
39             isContain = true;
40             break;
41         }
42         }
43         if (!isContain) {
44         List<T> newList = new ArrayList<>();
45         newList.add(list.get(i));
46         lists.add(newList);
47         }
48     }
49     return lists;
50     }
51 
52     public static void main(String[] args) {
53     List<Apple> list = new ArrayList<>();
54     list.add(new GroupTest().new Apple("紅", 205));
55     list.add(new GroupTest().new Apple("紅", 131));
56     list.add(new GroupTest().new Apple("綠", 248));
57     list.add(new GroupTest().new Apple("綠", 153));
58     list.add(new GroupTest().new Apple("黃", 119));
59     list.add(new GroupTest().new Apple("黃", 224));
60     List<List<Apple>> byColors = dividerList(list, new Comparator<Apple>() {
61 
62         @Override
63         public int compare(Apple o1, Apple o2) {
64         // 按顏色分組
65         return o1.color.compareTo(o2.color);
66         }
67     });
68     System.out.println("按顏色分組" + byColors);
69     List<List<Apple>> byWeight = dividerList(list, new Comparator<Apple>() {
70 
71         @Override
72         public int compare(Apple o1, Apple o2) {
73         // 按重量級
74 
75         return (o1.weight / 100 == o2.weight / 100) ? 0 : 1;
76         }
77     });
78     System.out.println("按重量級分組" + byWeight);
79     }
80 }

結果如下(為了方便看,手動回車換行格式化了下):
按顏色分組
[
[
Apple [color=紅, weight=205],
Apple [color=紅, weight=131]
],
[
Apple [color=綠, weight=248],
Apple [color=綠, weight=153]
],
[
Apple [color=黃, weight=119],
Apple [color=黃, weight=224]
]
]

按重量級分組
[
[
Apple [color=紅, weight=205],
Apple [color=綠, weight=248],
Apple [color=黃, weight=224]
],
[
Apple [color=紅, weight=131],
Apple [color=綠, weight=153],
Apple [color=黃, weight=119]
]
]

5.總結

一般需要做比較的邏輯都可以使用的上Comparator,最常用的場景就是排序和分組,排序常使用Arrays和Collections的sort方法,而分組則可以使用上面提供的dividerList方法。

排序和分組的區別在於:
排序時,兩個對象比較的結果有三種:大於,等於,小於。
分組時,兩個對象比較的結果只有兩種:等於(兩個對象屬於同一組),不等於(兩個對象屬於不同組)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM