當前位置:
首頁 > 知識 > 似懂非懂 Comparable和 Comparator

似懂非懂 Comparable和 Comparator

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


Comparable

首先看下 Comparable,Comparable 它可以看成是一個排序介面,一個類實現了該介面,就表示該類本身具有排序的功能,如果對該類的集合或者數組進行排序,則可以使用 Collections.sort() 和 Arrays.sort() 進行排序而不用再指定額外的比較器;

此外,實現了該介面的類,也可以作為 SortedMap 和 SortedSet 的 key 也不用再指定額外的比較器, 但是,如果需要把實現了該介面的類當作 SortedMap 的 Key 或者 放入到 SortedSet 中,需要保證 e1.compareTo(e2) == 0 和 e1.equals(e2) 相等,

但是有一點需要注意的是:因為 e.equal(null) 會返回false,所以,當我們需要比較的對象為 null 的時候,應該拋出一個 空指針異常。

接下來看下 Comparable 介面的方法,該介面下只有一個方法:

public int compareTo(T o);

該介面返回一個 int 類型,有三種情況:

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

若 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 更多的像一個外部比較器

似懂非懂 Comparable和 Comparator

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

C井——分享幾種常用的編碼轉換,base64、MD5、string
數據抽取清洗轉換載入工具ETL

TAG:程序員小新人學習 |