Comparator是一個(gè)專用的比較器,當(dāng)這個(gè)對(duì)象不支持自比較或者自比較函數(shù)不能滿足要求時(shí)惕味,可寫一個(gè)比較器來完成兩個(gè)對(duì)象之間大小的比較。Comparator體現(xiàn)了一種策略模式(strategy design pattern),就是不改變對(duì)象自身,而用一個(gè)策略對(duì)象(strategy object)來改變它的行為胖眷。
比如我有一組數(shù)字需要對(duì)其進(jìn)行正序排序,java8之前我們通常的做法是:
Integer [] values = new Integer[]{1,0,3,5,7,8,5,4,3,7,9,56,3,23};
Arrays.sort(values, new Comparator<Integer>() {
@Override
public int compare(Integer value1, Integer value2) {
return value1- value2;
}
});
而在java8中,由于新增lambda表達(dá)式,我們可以很簡(jiǎn)潔的使用如下的方式:
Integer [] values = new Integer[]{1,0,3,5,7,8,5,4,3,7,9,56,3,23};
Arrays.sort(values, (x,y) -> x-y);
可以看到代碼量更加簡(jiǎn)潔更加清晰,jdk甚至為了排序做了一些定制的方法,比如上面的代碼可以寫成如下的方式,更加讓人容易理解:
Integer [] values = new Integer[]{1,0,3,5,7,8,5,4,3,7,9,56,3,23};
Arrays.sort(values, Comparator.comparingInt(x -> x));
由于本文不會(huì)專門講解java8中關(guān)于lambda表達(dá)式的內(nèi)容,只講解主題相關(guān)的Comparator的使用,如果想了解更多關(guān)于lambda表達(dá)式的內(nèi)容,還請(qǐng)參考其他文章.
Comparator使用
Comparator是一個(gè)函數(shù)式接口,只有一個(gè) int compare(T o1, T o2);方法供外部使用,但是java8在其基礎(chǔ)上定制了許多default方法,這些default方法,開箱即用,下面我們就看看有哪些default方法以及如何使用.
reversed()
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
顧名思義,可以知道這個(gè)方法是用來生成一個(gè)逆序器,比如我們開始需要得到一個(gè)正序的排序序列,然后又想得到一個(gè)反轉(zhuǎn)的排序序列,就可以使用該方法,比如:
Integer [] values = new Integer[]{1,0,3,5,7,8,5,4,3,7,9,56,3,23};
Comparator<Integer> comparator = Comparator.comparingInt(x -> x);
Arrays.sort(values, comparator);
System.out.println(JSON.toJSONString(values));
Arrays.sort(values, comparator.reversed());
System.out.println(JSON.toJSONString(values));
結(jié)果如下:
[0,1,3,3,3,4,5,5,7,7,8,9,23,56]
[56,23,9,8,7,7,5,5,4,3,3,3,1,0]
可以看到,先得到正序排序的序列,然后調(diào)用comparator.reversed(),我們將內(nèi)容進(jìn)行反轉(zhuǎn)
thenComparing(Comparator<? super T> other)
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
顧名思義,該方法是在原有的比較器上再加入一個(gè)比較器,比如我們有一些用戶,在對(duì)其進(jìn)行排序的時(shí)候,我們首先對(duì)他的名字長度進(jìn)行排序,然后再對(duì)他的年齡進(jìn)行排序,如下:
person類
class Person{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
測(cè)試代碼:
Person [] persons = new Person[]{
new Person(22,"zhangsan"),
new Person(23,"lisi"),
new Person(23,"wangwu"),
new Person(22,"wangwu"),
new Person(22,"lisi"),
new Person(23,"zhangsan")
};
System.out.println(JSON.toJSONString(persons));
Comparator<Person> comparator = Comparator.comparingInt(x -> x.name.length());
Arrays.sort(persons,comparator);
System.out.println(JSON.toJSONString(persons));
comparator = comparator.thenComparing(Comparator.comparingInt(x->x.age));
Arrays.sort(persons,comparator);
System.out.println(JSON.toJSONString(persons));
結(jié)果如下:
[{"age":22,"name":"zhangsan"},{"age":23,"name":"lisi"},{"age":23,"name":"wangwu"},{"age":22,"name":"wangwu"},{"age":22,"name":"lisi"},{"age":23,"name":"zhangsan"}]
[{"age":23,"name":"lisi"},{"age":22,"name":"lisi"},{"age":23,"name":"wangwu"},{"age":22,"name":"wangwu"},{"age":22,"name":"zhangsan"},{"age":23,"name":"zhangsan"}]
[{"age":22,"name":"lisi"},{"age":23,"name":"lisi"},{"age":22,"name":"wangwu"},{"age":23,"name":"wangwu"},{"age":22,"name":"zhangsan"},{"age":23,"name":"zhangsan"}]
上述代碼甚至可以簡(jiǎn)化成如下:
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge);
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
待補(bǔ)充