iT邦幫忙

2025 iThome 鐵人賽

DAY 1
0
自我挑戰組

從0開始學習Java系列 第 1

Comparable vs Comparator 差異比較

  • 分享至 

  • xImage
  •  

一、Comparable 和 Comparator 架構圖
java.util.Collection (介面)

├── java.util.List (介面) -- 有序,可重複
│ ├── java.util.ArrayList (類別) -- 動態陣列
│ ├── java.util.LinkedList (類別) -- 雙向鏈結串列
│ └── java.util.Vector (類別) -- 執行緒安全的動態陣列

├── java.util.Set (介面) -- 無序,不重複
│ ├── java.util.HashSet (類別) -- 基於 HashMap
│ ├── java.util.LinkedHashSet (類別) -- 保留插入順序
│ └── java.util.TreeSet (類別) -- 基於紅黑樹,自然排序

└── java.util.Queue (介面) -- 先進先出(FIFO)
├── java.util.PriorityQueue (類別) -- 依優先級排序
└── java.util.Deque (介面) -- 雙端隊列
├── java.util.ArrayDeque (類別)
└── java.util.LinkedList (類別) -- 也同時實作了 List

二、Comparable 和 Comparator 的差異
特性:
2個介面Comparable、Comparator,用來排序物件

Module.java.base
Package.java.lang
Interface Comparable<T>

Module.java.base
Package.java.util
Interface Comparator<T>

在 Java 中,ComparableComparator 介面都是用於對物件進行排序。
它們的主要差異如下:

  • Comparable:用於在類別內定義物件的自然排序方式。
  • Comparator:用於在類別外部定義自訂的排序邏輯。

三、ComparableComparator` 的差異比較表

補充:什麼是自然排序?
答案:數字排在大寫字母之前,大寫字母排在小寫字母之前。

四、實作一個Comparable範例

  1. 新增Laptop類別
  2. Laptop類別要繼承java.util.Comparator 介面
  3. 裡面設定三個欄位 (brand, ram ,price)
  4. 設定所有欄位的Setter, Getter
  5. 使用右鍵>> source >> Generate toString()
  6. Laptop類別實作Comparable<Laptop>介面
  7. 複寫compareTo方法

Laptop.java

package Geeks;
import java.util.Comparator;

public class Laptop implements Comparable<Laptop>{
	private String brand;
	private int ram;
	private int price;

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}
 
	public int getRam() {
		return ram;
	}

	public void setRam(int ram) {
		this.ram = ram;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
	return "Laptop [brand=" + brand + ", ram=" + ram + ", price=" + price + "]";
	}

	//加上建構子,才可以在ComparableRunner.java使用new Laptop("Apple",8,1200)等
	public Laptop(String brand, int ram, int price) {
		super();
		this.brand = brand;
		this.ram = ram;
		this.price = price;
	}

	@Override
	public int compareTo(Laptop lap2) {
		//需要一個參數來做排序
		//this是"本物件"
		//this > lap2 = 正數
		//this < lap2 = 負數
		//this == lap2 0

		//使用ram這個欄位自然排序
		if(this.getRam() > lap2.getRam()) {
			return 1; //回傳正數
		}else {
			return -1;
		}
	}
}

ComparableRunner.java

package Geeks;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparableRunner {

	public static void main(String[] args) {
		List<Laptop> laps = new ArrayList<>();
		laps.add(new Laptop("Acer", 12, 700));
		laps.add(new Laptop("Asus", 8, 600));
		laps.add(new Laptop("Dell", 6, 900));
		laps.add(new Laptop("Apple", 8, 1200));
		
		//不知道要用哪一個排序brand or ram or price
		//Collection是泛型介面,是集合家族的共同祖先。Collection有2個很重要的子介面: Set、List
		//Collections 工具類別 - 用於List物件
		//將List傳送進Collections.sort的方法
		Collections.sort(laps);
		
		for(Laptop l: laps) {
			System.out.println(l);
		}

	}
}

五、實作一個Comparator範例

package Geeks;
import java.util.Comparator;

// 不需要實作 Comparator 介面
public class Laptop{
	private String brand;
	private int ram;
	private int price;
	
	public String getBrand() {
		return brand;
	}
	
	public void setBrand(String brand) {
		this.brand = brand;
	}
	
	public int getRam() {
		return ram;
	}
	
	public void setRam(int ram) {
		this.ram = ram;
	}
		
	public int getPrice() {
		return price;
	}
	  	
	public void setPrice(int price) {
		this.price = price;
	}
		
	@Override
	public String toString() {
	return "Laptop [brand=" + brand + ", ram=" + ram + ", price=" + price + "]";
	}
	
	
	//加上建構子
	public Laptop(String brand, int ram, int price) {
		super();
		this.brand = brand;
		this.ram = ram;
		this.price = price;
	}
}

ComparatorRunner.java

package Geeks;

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

public class ComparatorRunner {
	public static void main(String[] args) {
		List<Laptop> laps = new ArrayList<>();
		laps.add(new Laptop("MSI", 10, 1000));
		laps.add(new Laptop("Sony", 8, 600));
		laps.add(new Laptop("Lenovo", 6, 900));
		laps.add(new Laptop("Asus", 8, 1200));

		Comparator<Laptop> com = new Comparator<>() {

					
			//依品牌字母順序
			public int compare(Laptop l1, Laptop l2) {
			    return l1.getBrand().compareTo(l2.getBrand());
			}
		};

		Collections.sort(laps, com);

		for (Laptop l : laps) {
			System.out.println(l);
		}
	}
}

參考資料
Interview Question | Comparable vs Comparator in Java
https://www.youtube.com/watch?v=oAp4GYprVHM

Java Comparable vs Comparator
https://www.geeksforgeeks.org/java/comparable-vs-comparator-in-java/


下一篇
利用Comparator製作更客製化的排序
系列文
從0開始學習Java21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言