【轉】Java中對集合進行排序的兩種方法

Collections 是集合的工具類,它提供了很多便於我們操作集合的方法, 其中就有用於集合排序的 sort 方法。
在這裏插入圖片描述
實際上,在使用Collection的sort排序的集合元素都必須是Comparable 接口的實現類,該接口表示子類是可以比較的。因爲實現接口必須重寫抽象方法 - int compareTo(T t)。

一、對於基礎數據類型集合的比較

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class Test1 {
	public static void main(String[] args) {
		List<Integer> list0 = new ArrayList<>();
		Random random = new Random();
		for(int i = 0; i<10;i++){
			list0.add(random.nextInt(100));
		}
		System.out.println(list0);//[46, 7, 91, 48, 52, 25, 64, 3, 28, 60]
		/*
		 * 對集合進行自然排序,從小到大
		 */
		Collections.sort(list0);
		System.out.println(list0);//[2, 19, 44, 46, 61, 67, 68, 89, 91, 94]
			
		List<String> list1 = new ArrayList<>();
		list1.add("Alive");
		list1.add("Rose");
		list1.add("Jack");
		list1.add("Noname");
		System.out.println(list1); //[Alive, Rose, Jack, Noname]
		Collections.sort(list1);
		/*
		 *對集合進行自然排序,顯而易見是按照首字母順序排序
	   	 */
		System.out.println(list1);//[Alive, Jack, Noname, Rose]
		}
}

那麼你有沒有發現在該類中我並沒有實現Comparable接口,那麼爲什麼
我對 list0 和 list1集合排序時沒有報錯呢?
在這裏插入圖片描述
在這裏插入圖片描述
原因:查詢源碼可知 Integer、String 類都實現了Comparable接口,所以在對list0和list1集合排序時沒有報錯。

二、對於集合中的對象比較(自定義排序)

那麼問題來了對象這個大小之分是如何判斷呢?

實際上,在使用Collection的sort排序的集合元素都必須是Comparable接口的實現類,該接口表示子類是可以比較的。
因爲實現接口必須重寫抽象方法。

  • int compareTo(T t);
    該方法用於使當前對象與給定對象進行比較。
    返回值爲一個int值,該值表示大小關係,它不關注具體的取值是多少,而關注的是取值範圍。
    當返回值>0時:當前對象比參數對象大
    當返回值<0時:當前對象比參數對象小
    當返回值=0時:當前對象等於參數對象

cell類

public class Cell implements Comparable<Cell>{
	//哪個類實現Comparable接口泛型就寫哪個類
	private  int x;
	private  int y;
	public Cell(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	@Override
	public String toString() {
		return "Cell [x=" + x + ", y=" + y + "]";
	}
	@Override
	public int compareTo(Cell o) {
		//自定義排序邏輯
		// TODO Auto-generated method stub
		return this.x-o.x; //以傳入的Cell的橫座標由小到大進行排序
	}
  
}
	 @Test
    public void testComparable(){
    	/*
    	 * Cell實現了Comparable接口,compareTo方法邏輯爲按照x值大小進行排序
    	 */
    	List<Cell> cells = new ArrayList<Cell>();
    	cells.add(new Cell(2,3));
    	cells.add(new Cell(5,1));
    	cells.add(new Cell(3,2));
    	//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]
    	System.out.println(cells);
    	Collections.sort(cells);
    	//[Cell [x=2, y=3], Cell [x=3, y=2], Cell [x=5, y=1]]
    	System.out.println(cells);
    }

我們想使用sort方法排序集合,但是該方法要求我們的集合元素必須實現Comparable接口並且定義比較規則,這種我們想使用某個功能,而它要求我們修改程序的現象稱爲“侵入性”。修改的代碼越多,侵入性比較強,越不利於程序的擴展。
所以不建議使用這個構造方法。

三、重用重載的 Collections.sort(List,Comparator)方法

重載的sort方法要求傳入一個額外的比較器
該方法不再要求集合元素必須實現Comparable接口,並且也不再使用集合元素自身的比較規則排序了,而是根據給定的這個額外的比較器的比較規則對集合元素進行排序。
實際開發中也推薦使用這種方式排序集合元素,若集合元素是自定義的,創建比較器時也推薦使用匿名內部類的形式。

方法一:自定義一個比較器然後傳入Collections.sort(List,Comparator)中。

測試代碼:

自定義的比較器:

import java.util.Comparator;

public class MyComparator implements Comparator<Cell>{
	@Override
	public int compare(Cell o1, Cell o2) {
		//根據傳入的cell的y座標由小到大進行排序
		return o1.getY()-o2.getY();
	}
}

測試類:

	@Test
    public void testComparator() {
    	List<Cell> cells = new ArrayList<>();
    	cells.add(new Cell(2,3));
    	cells.add(new Cell(5,1));
    	cells.add(new Cell(3,2));
    	//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]
    	System.out.println(cells);
    	MyComparator com = new MyComparator();
    	Collections.sort(cells,com);
    	//根據自定義排序後的結果:[Cell [x=5, y=1], Cell [x=3, y=2], Cell [x=2, y=3]]
    	System.out.println(cells);
    } 

方法二:採用匿名內部的形式(推薦做法)

	@Test
    public void testComparator() {
    	List<Cell> cells = new ArrayList<>();
    	cells.add(new Cell(2,3));
    	cells.add(new Cell(5,1));
    	cells.add(new Cell(3,2));
    	System.out.println(cells);//[Cell [x=2, y=3], Cell [x=5, y=1], Cell [x=3, y=2]]
    	Collections.sort(cells,new Comparator<Cell>(){
    	//此處創建了一個匿名內部類
		@Override
		public int compare(Cell o1,Cell o2){
			return o1.getY() - o2.getY();
		}

	});
    	System.out.println(cells);//[Cell [x=5, y=1], Cell [x=3, y=2], Cell [x=2, y=3]]
    } 

比較總結:

  • 對於基礎數據類型集合比較使用Collections.sort();
  • 對於集合中的對象比較,需要指定比較邏輯,指定比較邏輯需要實現 Comparable接口並重寫compareTo方法自定義邏輯。
  • 對於需要臨時改變比較規則,需要使用Collections.sort(List,Comparator),採用回調方式重寫Comparator接口的compare方法自定義邏輯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章