Java排序之Comparable和Comparator比較器詳解
Comparable和Comparator比較器
Comparable<T>和 Comparator<T>這倆接口經(jīng)常被使用,這里介紹下這倆是什么以及怎么用
Comparable<T>和Comparator<T>一般都是用來排序?qū)ο蟮?
Comparable<T>是內(nèi)部比較器,Comparator<T>是外部比較器,直接上代碼看例子
1.Comparable<T>
Comparable<T>內(nèi)部比較器,故那個類需要排序能力就實現(xiàn)它
使用方式
1.如果我們想讓List<SortA>按一定方式排序,可以將SortA實現(xiàn) Comparable<SortA>接口,重寫compareTo(SortA s)方法
@Data
public class SortA implements Serializable, Comparable<SortA>{
@ApiModelProperty("名字")
private String name;
@ApiModelProperty("年齡")
private Integer age;
//自定義排序規(guī)則
@Override
public int compareTo(SortA o) {
return this.age - o.getAge(); //升序
//return this.age.compareTo( o.getAge()); //升序
//return o.getAge() - this.age; //倒序
//return o.getAge().compareTo(this.age); //倒序
//return -1; //自然排序的倒序
//return 1 或 0; //自然排序
}
}
public class 排序 {
public static void main(String[] args) {
//創(chuàng)造數(shù)據(jù)
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a張三");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("c李四");
a2.setAge(16);
SortA a3 = new SortA();
a3.setName("b王五");
a3.setAge(17);
listA.add(a1);
listA.add(a2);
listA.add(a3);
//調(diào)用方法
testComparable(listA);
}
public static void testComparable(List<SortA> listA) {
//排序方法Collections.sort(List<T> list);
//內(nèi)部使用 Arrays.sort(a, (Comparator) c);
//所以如果數(shù)據(jù)是是數(shù)組,可以直接用Arrays.sort(數(shù)據(jù))來排序
Collections.sort(listA);
System.out.println("Comparable排序:" + listA);
//Comparable排序:[SortA(name=李四, age=16), SortA(name=王五, age=17), SortA(name=張三, age=18)]
}
}
2.Comparator<T>
我們可以發(fā)現(xiàn)Comparable<T>代碼侵入性比較強,而且不夠靈活,我們同一對象每次排序的規(guī)則不可能都一樣,那么就可以外部比較器Comparator<T>
使用方式
2.1 Comparator可以不由SortA實現(xiàn),可以實現(xiàn)一個SortAComparator排序類
//注意泛型是需要排序的類SortA
public class SortAComparator implements Comparator<SortA> {
/**
* compare()和compareTo()很像,返回值參照compareTo(),o1相當于this
*/
@Override
public int compare(SortA o1, SortA o2) {
int sort = o1.getAge() - o2.getAge();
return sort;
}
}
2.2 Comparable是一個函數(shù)式接口,所以可以使用匿名內(nèi)部類或者Lambda表達式(常用)來實現(xiàn)
甚至jdk8以后Comparable<T>提供了很多static方法直接供我們使用
2.3 直接上代碼
public class 排序 {
public static void main(String[] args) {
//創(chuàng)造數(shù)據(jù)
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a張三");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("c李四");
a2.setAge(16);
SortA a3 = new SortA();
a3.setName("b王五");
a3.setAge(17);
listA.add(a1);
listA.add(a2);
listA.add(a3);
//調(diào)用方法
testComparator(listA);
}
public static void testComparator(List<SortA> listA) {
//外部比較器,實現(xiàn)Comparator接口
//1.SortAComparator實現(xiàn)Comparator接口
listA.sort(new SortAComparator());
System.out.println(listA);
//2.使用匿名內(nèi)部類或Lambda,表達式
listA.sort(new Comparator<SortA>() {
@Override
public int compare(SortA o1, SortA o2) {
//年齡倒序
return o2.getAge() - o1.getAge();
}
});
//3.使用匿名內(nèi)部類或Lambda或Comparator的靜態(tài)方法"
//3.1按照名字正序排序
listA.sort(Comparator.comparing(SortA::getName));
System.out.println(listA);
//3.2按照名字倒序排序
listA.sort(Comparator.comparing(SortA::getName).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()));
System.out.println(listA);
}
}注意多條件情況!!
reversed和Comparator.reverseOrder()反轉(zhuǎn)順序的時機不同
Comparator.reverseOrder()會立即對此屬性排序
reversed()會得到左邊的結(jié)果后在排序
所以
Comparator.reverseOrder()是只針對當前屬性的反轉(zhuǎn),
reversed()會使左邊所有排序反轉(zhuǎn),注意這一點就行了
上測試~~
public class 排序 {
public static void main(String[] args) {
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("a");
a2.setAge(19);
SortA a3 = new SortA();
a3.setName("b");
a3.setAge(17);
SortA a4 = new SortA();
a4.setName("c");
a4.setAge(17);
SortA a5 = new SortA();
a5.setName("d");
a5.setAge(15);
listA.add(a1);
listA.add(a2);
listA.add(a3);
listA.add(a4);
listA.add(a5);
moreComparator(listA);
}
public static void moreComparator(List<SortA> listA){
//1.name正序,name一樣age正序
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge));
System.out.println(listA);
//2.name倒序,name一樣age正序
listA.sort(Comparator.comparing(SortA::getName).reversed().thenComparing(SortA::getAge));
System.out.println(listA); listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()).thenComparing(SortA::getAge));
System.out.println(listA);
//3.name倒序,name一樣age倒序
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName,Comparator.reverseOrder()).thenComparing(SortA::getAge,Comparator.reverseOrder()));
System.out.println(listA);
//4.name正序,name一樣age倒序
listA.sort(Comparator.comparing(SortA::getName).reversed().thenComparing(SortA::getAge).reversed());
System.out.println(listA);
listA.sort(Comparator.comparing(SortA::getName).thenComparing(SortA::getAge,Comparator.reverseOrder()));
System.out.println(listA);
}
}注意對象為空或者屬性為空的情況
public class 排序 {
public static void main(String[] args) {
List<SortA> listA = new ArrayList<>();
SortA a1 = new SortA();
a1.setName("a");
a1.setAge(18);
SortA a2 = new SortA();
a2.setName("a");
a2.setAge(19);
SortA a3 = new SortA();
a3.setName("b");
a3.setAge(17);
SortA a4 = new SortA();
a4.setName("c");
a4.setAge(17);
SortA a5 = new SortA();
// a5.setName("d");
a5.setAge(15);
listA.add(a1);
listA.add(a2);
listA.add(a3);
listA.add(a4);
listA.add(a5);
listA.add(null);
nullComparator(listA);
}
//如果對象或者屬性為空
public static void nullComparator(List<SortA> listA){
//1.如果對象為空
listA.sort(Comparator.nullsFirst(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.naturalOrder()))));
System.out.println(listA);
//2.如果name為空
//自然排序
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.naturalOrder())));
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(String::compareTo)));
System.out.println(listA);
//反轉(zhuǎn)
listA.sort(Comparator.comparing(SortA::getName,Comparator.nullsFirst(Comparator.reverseOrder())));
System.out.println(listA);
}
}總結(jié)
- Comparable<T>是內(nèi)部比較器,Comparator<T>是外部比較器
- 最推薦使用Comparator<T>接口排序
- Comparator提供靜態(tài)方法很方便,推薦使用,不了解的可以先去學(xué)習(xí)函數(shù)式接口、Lambda、方法引用
- Comparator多條件排序時注意Comparator.reverseOrder()和reversed()的使用,
- Comparator排序時注意對象和屬性可能為空的情況,使用Comparator.nullsFirst()或者Comparator.nullsLast()
到此這篇關(guān)于Java排序之Comparable和Comparator比較器詳解的文章就介紹到這了,更多相關(guān)Comparable和Comparator比較器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS獲取AppIcon and LaunchImage''s name(app圖標和啟動圖片名字)
這篇文章主要介紹了iOS獲取AppIcon and LaunchImage's name(app圖標和啟動圖片名字)的相關(guān)資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-08-08

