Java Comparable 與Comparator

參考良葛格網站與官方API的Comparator與Comparable筆記

 

前言

在Java的規範中,跟順序有關的行為,通常要不物件本身是Comparable,要不就是另行指定Comparator物件告知如何排序。

引用自良葛格介紹Comparabla與Comparatorㄧ文中。

Java 8以前

    使用Collections.sort()方法傳入欲排序的List,但前提是該物件必須實作Comparable介面,否則會報錯

  public static <T extends Comparable<? super T>> void sort(List<T> list)

Java 8以後

    List介面加入sort默認方法可以使用

  default void sort(Comparator<? super E> c)

Comparable Interface

Comparable介面底下指有一個抽象方法需實作,ㄧ般來說常見的String、Integer、Double、BigDecimal....等都有實作Comparable,若需要課製化比較規則會使用Comparator

int compareTo(T o)

Compares this object with the specified object for order.

Comparator Interface

Functional Interface:
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

Comparator為ㄧ個Functional Interface 可供lamda expression or 其他方法參考,其中compare為其抽象方法,用法與Comparable介面的compareTo類似,

int compare(T o1, T o2)

Compares its two arguments for order.

Comparable v.s. Comparator

  • 從英文字面上比較

                   Comparable:可比較的--->通常用在物件implements使用,例如String、Integer、BigDecimal.....

                   Comparator:比較器--->應用範圍廣,此介面提供很多默認方法供lamda expression使用

  • 在某些情況下雖然物件有實作Comparable但我們卻無法改變其排序行為,例如String類別想要讓排序結果反序,此時我們可以時作ㄧ個String比較器供Collections.sort使用
  • Collections.sort()有多載方法供Comparable與Comparator使用

Collections.sort()的範例

public static <T extends Comparable<? super T>> void sort(List<T> list) API連結
public static <T> void sort(List<T> , Comparator<? super T> c) API連結
public class main {
	public static void main(String[] args) throws InterruptedException {
		List<String> list = Arrays.asList("Java","Python","C_sharp","R","Scala","Kotlin","Delphi");
		//直接按物件Comparable排序
		Collections.sort(list);
		System.out.println(list);//
		
		//比較器正規寫法  按字母反序
		Collections.sort(list, new StringComparator());
		System.out.println(list);
		//匿名類別寫法 按照字串長度由小到大
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.length()-o2.length();
			}} );

		System.out.println(list);// [R, Java, Scala, Python, Kotlin, Delphi, C_sharp]
		
		//lamda寫法 按照字串長度由大到小
		Collections.sort(list,(u,v)-> -(u.length()-v.length()));
		System.out.println(list); //[C_sharp, Python, Kotlin, Delphi, Scala, Java, R]
	}
}

class StringComparator implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		return -1*o1.compareTo(o2);
	}
}

List介面提供的sort默認方法

default void sort(Comparator<? super E> c) API連結

範例同上Collections.sort()傳入Comparator的方法

Comparator提供的默認方法應用

  • comparing
        static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor) API連結
  • reversed
        default Comparator<T> reversed()
public static void main(String[] args) throws InterruptedException {
	List<String> list = Arrays.asList("Java","Python","C_sharp","R","Scala","Kotlin","Delphi");
	
	list.sort(Comparator.comparing(String::length));
	list.sort(Comparator.comparing( s-> s.length()) );
	list.sort(Comparator.<String,Integer>comparing(s->s.length()));
	System.out.println(list);//[R, Java, Scala, Python, Kotlin, Delphi, C_sharp]
	
    //reverse
	list.sort(Comparator.comparing(String::length).reversed());
	System.out.println(list);//[C_sharp, Python, Kotlin, Delphi, Scala, Java, R]
}

Reference: