1. 程式人生 > >Comparable和Comparator的區別

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)。