似懂非懂 Comparable和 Comparator

在java中提供了兩種排序方式:Comparable和 Comparator,它們兩個看起來很是的類似,在不是很瞭解的狀況下不知道如何使用,什麼狀況下使用哪一個進行排序,接下來就看下它們的一個區別和使用方式:java

Comparable

首先看下 Comparable,Comparable 它能夠當作是一個排序接口,一個類實現了該接口,就表示該類自己具備排序的功能,若是對該類的集合或者數組進行排序,則可使用 Collections.sort() 和 Arrays.sort() 進行排序而不用再指定額外的比較器;數組

此外,實現了該接口的類,也能夠做爲 SortedMap 和 SortedSet 的 key 也不用再指定額外的比較器, 可是,若是須要把實現了該接口的類看成 SortedMap 的 Key 或者 放入到  SortedSet 中,須要保證 e1.compareTo(e2) == 0 和 e1.equals(e2) 相等,ide

可是有一點須要注意的是:由於 e.equal(null) 會返回false,因此,當咱們須要比較的對象爲 null 的時候,應該拋出一個 空指針異常。this

接下來看下 Comparable 接口的方法,該接口下只有一個方法:spa

public int compareTo(T o);

該接口返回一個 int 類型,有三種狀況:指針

若 e1 > e2 則 e1.compateTo(e2) > 0,返回正數code

若 e1 = e2 則 e1.compateTo(e2) = 0,返回0對象

若 e1 < e2 則 e1.compateTo(e2) < 0,返回負數排序

接下來看下如何使用:接口

首先定義一個類實現該接口,以後重寫 compareTo() 方法,通常也須要重寫 equal()  和 hashcode() 方法:

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User implements Comparable<User> {

    private String name;

    private int age;

    private String job;

    @Override
    public int compareTo(User o) {
        return getName().compareTo(o.getName());
    }

    @Override
    public int hashCode() {
        return getName().hashCode() * 31 + getAge();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj){
            return true;
        }
        if (! (obj instanceof User)){
            return false;
        }
        User u = (User)obj;
        return (getName().equals(u.getName())) && (getAge() == u.getAge()) && (getJob().equals(u.getJob()));
    }
}

接下來就能夠對 該類進行排序了:

首先建立該對象的一個集合:

User u1 = new User("zhangsan", 28, "C++");
        User u2 = new User("zhangsan", 28, "C++");
        User u3 = new User("wangwu", 22, "C");
        User u4 = new User("xiaoliu", 26, "Python");
        User u5 = new User("jiqjiq", 11, "Go");

        System.out.println(u1.equals(u2)); // true
        System.out.println(u1.compareTo(u2) == 0); // true

        List<User> users = Lists.newArrayList(u1, u2, u3, u4, u5);

以後,可使用   Collections.sort() 和 Arrays.sort() 進行排序,而不用再指定額外的比較器了:

System.out.println("排序以前...........");
        users.forEach((u) -> System.out.println(u));
        
        // 排序
        Collections.sort(users);

        System.out.println("排序以後...");
        users.forEach((u) -> System.out.println(u));

結果:
排序以前...........
User(name=zhangsan, age=28, job=C++)
User(name=zhangsan, age=28, job=C++)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=jiqjiq, age=11, job=Go)
排序以後...
User(name=jiqjiq, age=11, job=Go)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=zhangsan, age=28, job=C++)
User(name=zhangsan, age=28, job=C++)

以後,還能夠把這些對象放入到 SortedSet 中,就會天然對這些對象進行排序:

TreeSet<User> treeSet = new TreeSet<>(users);

treeSet.forEach((user -> System.out.println(user)));

結果:

User(name=jiqjiq, age=11, job=Go)
User(name=wangwu, age=22, job=C)
User(name=xiaoliu, age=26, job=Python)
User(name=zhangsan, age=28, job=C++)

由於 Set 中沒有重複元素,全部會過濾掉重複的元素。

在java的核心類庫中,一些類已經實現該接口,因此能夠直接對應它們進行排序,如 String , Integer 等:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence 

public final class Integer extends Number implements Comparable<Integer> 


List<String> strings = Lists.newArrayList("c", "e", "a", "b", "d");
Collections.sort(strings);

List<Integer> integers = Lists.newArrayList(3, 2, 4, 1, 5);
Collections.sort(integers);

Comparator

Comparator 能夠把它當作是一個比較器接口,它是一個比較器,實現該接口的類自己沒有比較的功能,只是用它去對其餘的元素進行排序:

Comparator 接口有兩個方法:

int compare(T o1, T o2);
boolean equals(Object obj);

還有一些默認的方法,都是一些 java8 中的方法,

自定義一個比較器:

public class UserSortByName implements Comparator<User1> {

    @Override
    public int compare(User1 o1, User1 o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

以後就可使用該自定義的比較器對集合進行排序:

List<User1> users1 = Lists.newArrayList(u11, u21, u31, u41, u51);
 Collections.sort(users1, new UserSortByName());

固然,也能夠不用自定義一個比較器,直接使用匿名類便可,以下:

// 排序
        Collections.sort(users1, new Comparator<User1>() {
            @Override
            public int compare(User1 o1, User1 o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

        // lambda 表達式的寫法:

        Collections.sort(users1, Comparator.comparing(User1::getName));


        // 添加到 SortedSet 中
        TreeSet<User1> treeSet1 = new TreeSet<>(new Comparator<User1>() {
            @Override
            public int compare(User1 o1, User1 o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        treeSet1.addAll(users1);
        
        // lambda 表達式寫法
        TreeSet<User1> treeSet2 = new TreeSet<>(Comparator.comparing(User1::getName));
        treeSet2.addAll(users1);

總結:

Comparable 它是一個排序接口,實現該接口的類自己具備排序的功能,能夠直接使用 Collections.sort() 和 Arrays.sort() 進行排序而不用再指定額外的比較器;也能夠直接放入到 SortedSet 和 SortedMap 中的保證其有序;

Comparator 它是一個比較器,實現該接口的類只能用其對其餘對象進行排序;

Comparable 更多的像一個內部比較器,而 Comparator  更多的像一個外部比較器

相關文章
相關標籤/搜索