Comparable和Comparator的區別

概要:

  Comparable和Comparator都是用於比較數據的大小的,實現Comparable接口需要重寫compareTo方法,實現Comparator接口需要重寫compare方法,這兩個方法的返回值都是int,用int類型的值來確定比較結果,在Collections工具類中有一個排序方法sort,此方法可以之傳一個集合,另一個重載版本是傳入集合和比較器,前者默認使用的就是Comparable中的compareTo方法,後者使用的便是我們傳入的比較器Comparator,java的很多類已經實現了Comparable接口,比如說String,Integer等類,而我們其實也是基於這些實現了Comparator或者Comparab接口的原生類來比較我們自己的類,比如說自定義一個類User,屬性有name和age,倆個user之間的比較無非就是比較name和age的大小。

Comparable:

  Comparable接口中只有一個方法:

public int compareTo(T o);

  調用此方法的對象,也就是this和o進行比較,若返回值大於0則this大於o,返回值等於0則是this等於o,返回值小於0則是this<o,而這個Comparable是直接在我們的自定義類User上實現,因爲this是需要一個明確的比較對象的,也就是一般情況下我們會在定義User類的時候有排序的需求,就要實現此接口。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class UserComparable implements Comparable<UserComparable> {
    private String name;
    private int age;

    public UserComparable(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "UserComparable{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(UserComparable o) {
        if (this.name.compareTo(o.name)==0){
            if (this.age == o.age){
                return 0;
            }else if (this.age >o.age){
                return 1;
            }else {
                return -1;
            }
        }else if (this.name.compareTo(o.name)>0){
            return 1;
        }else {
            return -1;
        }
    }

    public static void main(String[] args) {
        List<UserComparable> list = new ArrayList<UserComparable>();
        list.add(new UserComparable("gol",21));
        list.add(new UserComparable("gol",19));
        list.add(new UserComparable("xiao",21));
        list.add(new UserComparable("long",21));
        System.out.println("排序前:"+list);
        //排序規則:先按name排序,若name相等則再比較age
        Collections.sort(list);
        System.out.println("排序後:"+list);
    }
}

  輸出結果爲:

    排序前:[UserComparable{name='gol', age=21}, UserComparable{name='gol', age=19}, UserComparable{name='xiao', age=21}, UserComparable{name='long', age=21}]
    排序後:[UserComparable{name='gol', age=19}, UserComparable{name='gol', age=21}, UserComparable{name='long', age=21}, UserComparable{name='xiao', age=21}]

Comparator:

  Comparator接口中方法很多,但是我們只需要實現一個,也是最重要的一個compare,也許有的人會好奇爲什麼接口中的方法可以不用實現,因爲這是JDK8以後的新特性,在接口中用default修飾的方法可以有方法體,在實現接口的時候可以不用重寫,可以類比抽象類。

  

int compare(T o1, T o2);

  compare比較的o1和o2,返回值大於0則o1大於o2,依次類推,對於compare;來說this是誰不重要,所比較的兩個對象都已經傳入到方法中,所有Comparator就是有個外部比較器,在我們設計User初時,並不需要它有比較功能,在後期擴展業務是,Comparator的存在可以使我們在不修改源代碼的情況下來完成需求,只需要新定義一個比較器來實現Comparator,重寫compare方法並將User對象傳進去。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public static void main(String[] args) {
        List<User> list = new ArrayList<User>();
        list.add(new User("gol", 21));
        list.add(new User("gol", 19));
        list.add(new User("xiao", 21));
        list.add(new User("long", 21));
        System.out.println("排序前:" + list);
        //排序規則:先按name排序,若name相等則再比較age
        //創建比較器對象
        Comparator comparator = new UserComparator();
        Collections.sort(list,comparator);
        System.out.println("排序後:" + list);
    }

    static class UserComparator implements Comparator<User> {

        @Override
        public int compare(User o1, User o2) {
            if (o1.name.compareTo(o2.name) == 0) {
                if (o1.age == o2.age) {
                    return 0;
                } else if (o1.age > o2.age) {
                    return 1;
                } else {
                    return -1;
                }
            } else if (o1.name.compareTo(o2.name) > 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }
}

  輸出結果爲:  

    排序前:[User{name='gol', age=21}, User{name='gol', age=19}, User{name='xiao', age=21}, User{name='long', age=21}]
    排序後:[User{name='gol', age=19}, User{name='gol', age=21}, User{name='long', age=21}, User{name='xiao', age=21}]

結論:

  java中大部分我們常用的數據類型的類都實現了Comparable接口,而僅僅只有一個抽象類RuleBasedCollator實現了Comparator接口 ,還是我們不常用的類,這並不是要用Comparab而不要使用Comparator,在設計初時有需求就選擇Comparable,若後期需要擴展或增加排序需求是,再增加一個比較器Comparator,畢竟能寫Collections.sort(arg1),沒人樂意寫Collections.sort(arg1,arg2)。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章