Collections用Comparable&&Comparator排序細節

在收集對象以後,對對象進行排序是經常使用的動做。不用親自操做排序算法Java.util. Collections提供有sort()方法。因爲必須有索引才能進行排序,所以 Collections的sort()方法接受List操做對象。例如:java

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List nums=Arrays.asList(3,6,2,7,5,9,0);
		Collections.sort(nums);
		System.out.println(nums);
	}
}

這裏寫圖片描述 1.操做 Comparable算法

package coll_map;

import java.util.*;

class Sort2 {
	private String name;
	private String ID;
	private int balance;

	Sort2(String name, String ID, int balance) {
		this.name = name;
		this.balance = balance;
		this.ID = ID;
	}
	
	@Override
	public String toString() {
		return String.format("帳戶(%s,%s,%d)", name,ID,balance);
	}
}
	public class Account{
		public static void main(String[] args) {
			List accounts=Arrays.asList(
					new Sort2("zhangsan","9958X",999),
					new Sort2("lisi","8779g",577),
					new Sort2("wanger","99098X",6988)
					);
			Collections.sort(accounts);
			System.out.println(accounts);
		}
	}

拋錯: java.lang.ClassCastException 是由於Collections的sort方法,不知道是根據 Account的name、ID或 balance進行排序。sort()方法要求被排序的對象必須操做java.lang. Comparable接口,這個接口有個 compareto()方法必須返回大於0、等於0或小於0的數:數組

package coll_map;

import java.util.*;

class Sort2 implements Comparable<Sort2>{
	private String name;
	private String ID;
	private int balance;

	Sort2(String name, String ID, int balance) {
		this.name = name;
		this.balance = balance;
		this.ID = ID;
	}
	
	@Override
	public String toString() {
		return String.format("帳戶(%s,%s,%d)", name,ID,balance);
	}

	@Override
	public int compareTo(Sort2 o) {
		// TODO 自動生成的方法存根
		return this.balance-o.balance;//判斷排序條件
	}
}
	public class Account{
		public static void main(String[] args) {
			List accounts=Arrays.asList(
					new Sort2("zhangsan","9958X",999),
					new Sort2("lisi","8779g",577),
					new Sort2("wanger","99098X",6988)
					);
			Collections.sort(accounts);
			System.out.println(accounts);
		}
	}

這裏寫圖片描述

collections的sot()方法在取得a對象與b對象進行比較時,會先將a對象扮演(Cast)爲 comparable(也所以若對象沒操做 Comparable,將會拋出 Classcastexception),而後調用 a.compareto(b),若是a對象順序上小於b對象則返回小於0的值,若順序上相等則返回0,若順序上a大於b則返回大於0的值。所以,上面的範例,將會依餘額從小到大排列帳戶對象。前面的Sort類中,能夠直接對 Integer進行排序,由於Integer就有操做 Comparable接口。 2.操做Comparator String有操做Comparable:ide

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List words=Arrays.asList("D","A","H","Y","E");
		Collections.sort(words);
		//若是隻想用String的compareTo方法能夠:words.sort(String::compareTo);
		System.out.println(words);
	}
}

這裏寫圖片描述 可是若是有對象沒法操做Comparable、拿不到原始碼或者不能修改原始碼。 好比讓String排序結果反過來,就算修改String. Java後從新編譯爲 String.clas放回 rt jar中,也只有這個的JRE能夠用,這已經不是標準API了。繼承 string後再從新定義 compareto()也不可能,由於 String聲明爲 final,不能被繼承。 Collections的sort()方法有另外一個重載版本,可接受 Java util. **Comparator接口的操做對象,若是使用這個版本,排序方式將根據 Comparator的 compare()定義來決定。**例如:this

package coll_map;
import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		Collections.sort(words,new StringSort());
		System.out.println(words);
	}
}
class StringSort implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		// TODO 自動生成的方法存根
		return -o1.compareTo(o2);
	}
}

Comparator的 compare()會傳入兩個對象,若是o1順序上小於o2則返回小於0的值,順序相等則返回0,順序上o1大於o2則返回大於0的值。在這個範例中,因爲 string自己就是 Comparable,因此將 compareto()返回的值乘上-1,就能夠調換排列順序。3d

package coll_map;

import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		//Collections.sort(words,(o1,o2) ->-o1.compareTo(o2));利用Lambda語法
		words.sort((o1,o2) ->-o1.compareTo(o2));//更簡單利用Lambda語法
		System.out.println(words);
	}
}

在Java的規範中,與順序有關的行爲,一般要不對象自己是 Comparable,要不就是另行指定 Comparator對象告知如何排序。 例如,若是想針對數組進行排序,可使用java.util.Arrays的sort()方法,若是查詢API文件,會發現該方法針對對象排序時有兩個版本:一個版本是你收集在數組中的對象必須是 Comparable()不然會拋出Classcastexception ,另外一個版本則能夠傳入 compa rato指定排序方式.
Set的操做類之一java. util. TreeSet不只擁有收集不重複對象的能力,還可用紅黑樹方式排序收集的對象,條件就是收集的對象必須是 comparable(不然會拋出 Classcastexception)或者是在建立TreeSet時指定 Comparator 對象。 Queue的操做類之一 java util. Priorityqueue也是,收集至 Priorityqueue的對象,會根據你指定的優先權來決定對象在隊列中的序,優先權的告知,要不就是對象必須是 comparable(不然會拋出Classcastexception)或者是建立Priorityqueue時指定Comparator對象。 若是有個List中某些索引處包括null,如今讓null排在最前頭,以後依字符串的長度由大到小排序,這樣從新定義compare:code

@Override
	public int compare(String o1, String o2) {
		if(o1==o2) {
			return 0;
		}
		if(o1==null) {
			return -1;
		}
		if(o2==null) {
			return 1;
		}
		if(o1.length()==o2.length()) {
			return 0;
		}
		if(o1.length()>o2.length()) {
			return -1;
		}
		return 1;
	}

固然其實能夠利用高級語義API:orm

package coll_map;
import java.util.*;
import static java.util.Comparator.*;

public class SortDemo {
	public static void main(String[] args) {
		List<String> words=Arrays.asList("D","A","H","Y","E");
		words.sort(nullsFirst(reverseOrder));//高級語義
		System.out.println(words);
	}
}

reverseOrder()返回的 Comparator會是 Comparable對象上定義順序的反序, nullsFirst接受 Comparator,在其定義的順序上加上讓null排在最前面的規則。 能夠看到 import static適當的運用,可讓程序碼錶達出自己操做的意圖相比如下程序代碼來講清楚許多:對象

words.sort(Comparator.nullsFirst(Comparator.reverseOrder));

Conparator上還有不少方法可使用,例如 comparing與 thenComparing等方法,要運用這些方法,得了解更多JDK8的 Lambda特性,例如位於java.util.function套件中的 Function等接口的意義blog

相關文章
相關標籤/搜索