天天看點

java 比較器comparator_Java比較器之Comparable 和 Comparator

前言

好久沒寫部落格了,今天研究了一下jdk的比較器,想着随手寫個部落格吧。

Comparable

首先介紹一下java.util.Comparable這個接口,該接口隻有一個方法:

public int compareTo(T o);

再簡單的引文注釋我也會翻譯,這是原則問題。那麼這裡的意思就是,傳入一個參數,進行比較,如果調用者比該參數“大”,那麼傳回正整數,反之傳回負整數,相同則傳回0。當然,這個”大”是由你自己去定義的。

在jdk8的源碼中,很多類都實作了這個接口,如Date,Long,String,Integer等等。看看Date對這個接口的實作源碼吧:

public int compareTo(Date anotherDate) {

long thisTime = getMillisOf(this);

long anotherTime = getMillisOf(anotherDate);

return (thisTime

}

如果this的日期在傳入參數的日期之前,那麼傳回負整數,反之傳回正整數,相等傳回0。這裡是通過比較兩個日期時間戳大小去實作的。

是以Comprable它就是一個很簡單的比較器規範。

Comparator

這個東西其實主要就是比較器的稍微進階應用。我看了源碼并且做了下翻譯,提取出了幾個關鍵的方法。@FunctionalInterface

public interface Comparator {

int compare(T o1, T o2);

boolean equals(Object obj);

default Comparator reversed() {

return Collections.reverseOrder(this);

}

default Comparator thenComparing(Comparator super T> other) {

Objects.requireNonNull(other);

return (Comparator & Serializable) (c1, c2) -> {

int res = compare(c1, c2);

return (res != 0) ? res : other.compare(c1, c2);

};

}

//其實上個方法可以轉換成以下形式,這樣可能稍微接地氣些。

default Comparator thenComparing_back(Comparator super T> other) {

Objects.requireNonNull(other);

Comparator comparator = new Comparator() {

@Override

public int compare(T o1, T o2) {

int res = this.compare(o1, o2);

if (res != 0) {

return res;

}

return other.compare(o1, o2);

}

};

return comparator;

}

public static > Comparator reverseOrder() {

return Collections.reverseOrder();

}

@SuppressWarnings("unchecked")

public static > Comparator naturalOrder() {

return (Comparator) Comparators.NaturalOrderComparator.INSTANCE;

}

public static Comparator nullsFirst(Comparator super T> comparator) {

return new Comparators.NullComparator<>(true, comparator);

}

public static Comparator nullsLast(Comparator super T> comparator) {

return new Comparators.NullComparator<>(false, comparator);

}

public static > Comparator comparing(

Function super T, ? extends U> keyExtractor)

{

Objects.requireNonNull(keyExtractor);

return (Comparator & Serializable)

(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

}

}

應用場景List的排序List list = new ArrayList() {{

add(4);

add(444);

add(3);

add(2);

}};

//按升序排列

list.sort(null);

//按自然排序即升序排列

list.sort(Comparator.naturalOrder());

//按升序的逆序即降序排列,并且允許null值

list.sort(Comparator.nullsLast(Comparator.naturalOrder()).reversed());

//按升序的逆序即降序排列

Collections.sort(list,Comparator.nullsLast(Comparator.naturalOrder()).reversed());

System.out.println(Arrays.toString(list.toArray()));comparing方法public static > Comparator comparing(

Function super T, ? extends U> keyExtractor)

{

Objects.requireNonNull(keyExtractor);

return (Comparator & Serializable)

(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

}

該方法是靜态方法,傳入一個function對象,規則是先用function處理兩個比較參數key,再去比較這兩個key。方法傳回一個比較器,用于覆寫比較邏輯。

comparing方法的簡單應用:Function f = s -> s * s;

Comparator comparator = Comparator.comparing(f);

int compare = comparator.compare(6, 7);

System.out.println(compare);

//比較的是6*6和7*7,輸出-1

進階應用Comparator comparing = Comparator.comparing(Integer::intValue);

System.out.println(comparing.compare(3,43));

//比較的是3和43,輸出-1

//上面的Integer如果換成普通對象,一樣可以使用,例如對象DevelopDoc中包含getCreateTime()方法。

List docs=allDocs;

Collections.sort(docs, Comparator.comparing(DevelopDoc::getCreateTime));

這裡要提到的是“::”這個關鍵字,屬于java8的新特性,我們可以通過 :: 關鍵字來通路類的構造方法,對象方法,靜态方法。那麼如何通路其中的方法呢?我們先定義一個接口:@FunctionalInterface

static interface Te {

R apply(T t);

}

@FunctionalInterface注解的作用是,限定該接口隻能有一個可實作方法,其實不加此注解也沒問題,隻要不超過1個可實作方法就行,default和static方法不在範疇中。該接口定義了一個入參為T,傳回為R的apply方法。我們可以這樣使用它,Te t = s -> s + s;

System.out.println(t.apply(100));

//100+100, 輸出200

也可以這樣使用,//intValue()是Integer類的方法

Te test = Integer::intValue;

System.out.println(test.apply(100));

//輸入100,輸出200