1. 程式人生 > >【java】Comparator的用法

【java】Comparator的用法

原文連結:https://blog.csdn.net/u012250875/article/details/55126531 

1.為什麼寫?


comparator 是javase中的介面,位於java.util包下,該介面抽象度極高,有必要掌握該介面的使用
大多數文章告訴大家comparator是用來排序,但我想說排序是comparator能實現的功能之一,他不僅限於排序

2.介面功能


該介面代表一個比較器,比較器具有可比性!大多數文章都寫如何用comparator排序,是因為javase陣列工具類和集合工具類中提供的sort方法sort就是使用Comparator介面來處理排序的,大家見久了都認為Comparator介面是用來排序的,按照java抽象的尿性來看,該介面如果為排序而生,應該叫Sortable,Sortor之類的名字吧!下面是javase一些使用到Comparator介面的地方:

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


3.使用場景


什麼場景需要做比較,那麼什麼場景就是Comparator介面的用武之地,我總結的兩個場景: 
1. 排序,需要比較兩個物件誰排在前誰排在後(排序也可以讓類實現Comparable介面,實現後該類的例項也具有排序能力)。 
2. 分組,需要比較兩個物件是否是屬於同一組。 
3. 待補充

4.舉個栗子


1.排序 
在List或陣列中的物件如果沒有實現Comparable介面時,那麼就需要呼叫者為需要排序的陣列或List設定一個Compartor,Compartor的compare方法用來告訴程式碼應該怎麼去比較兩個例項,然後根據比較結果進行排序

talk is cheap show me the code

package com.java.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
 * @author puyf
 */
public class SortTest {
    class Dog{
    public int age;
    public String name;
    public Dog(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Dog [age=" + age + ", name=" + name + "]";
    }
    }
    public static void main(String[] args) {
    List<Dog> list= new ArrayList<>();
    list.add(new SortTest().new Dog(5, "DogA"));
    list.add(new SortTest().new Dog(6, "DogB"));
    list.add(new SortTest().new Dog(7, "DogC"));
    Collections.sort(list, new Comparator<Dog>() {

        @Override
        public int compare(Dog o1, Dog o2) {
        return o2.age - o1.age;
        }
    });
    System.out.println("給狗狗按照年齡倒序:"+list);
    Collections.sort(list, new Comparator<Dog>() {

        @Override
        public int compare(Dog o1, Dog o2) {
        return o1.name.compareTo(o2.name);
        }
    });
    System.out.println("給狗狗按名字字母順序排序:"+list);
    }
}


2.分組 


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

package com.java.demo;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
 * @author puyf
 */
public class GroupTest {
    class Apple {
    public String color;
    public int weight;

    public Apple(String color, int weight) {
        super();
        this.color = color;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple [color=" + color + ", weight=" + weight + "]";
    }
    }

    /**
     * @author puyf
     * @Description:按條件分組
     * @param datas
     * @param c
     *            是否為同一組的判斷標準
     * @return
     */
    public static <T> List<List<T>> divider(Collection<T> datas, Comparator<? super T> c) {
        List<List<T>> result = new ArrayList<List<T>>();
        for (T t : datas) {
            boolean isSameGroup = false;
            for (int j = 0; j < result.size(); j++) {
                if (c.compare(t, result.get(j).get(0)) == 0) {
                    isSameGroup = true;
                    result.get(j).add(t);
                    break;
                }
            }
            if (!isSameGroup) {
                // 建立
                List<T> innerList = new ArrayList<T>();
                result.add(innerList);
                innerList.add(t);
            }
        }
        return result;
    }

    public static void main(String[] args) {
    List<Apple> list = new ArrayList<>();
    list.add(new GroupTest().new Apple("紅", 205));
    list.add(new GroupTest().new Apple("紅", 131));
    list.add(new GroupTest().new Apple("綠", 248));
    list.add(new GroupTest().new Apple("綠", 153));
    list.add(new GroupTest().new Apple("黃", 119));
    list.add(new GroupTest().new Apple("黃", 224));
    List<List<Apple>> byColors = divider(list, new Comparator<Apple>() {

        @Override
        public int compare(Apple o1, Apple o2) {
        // 按顏色分組
        return o1.color.compareTo(o2.color);
        }
    });
    System.out.println("按顏色分組" + byColors);
    List<List<Apple>> byWeight = divider(list, new Comparator<Apple>() {

        @Override
        public int compare(Apple o1, Apple o2) {
        // 按重量級

        return (o1.weight / 100 == o2.weight / 100) ? 0 : 1;
        }
    });
    System.out.println("按重量級分組" + byWeight);
    }
}


結果如下(為了方便看,手動回車換行格式化了下): 
按顏色分組 


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方法,而分組則可以使用上面提供的divider方法。

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