Table of Contents
ToggleDifference Between Comparable and Comparator in Java
兩種接口都是常用於集合或陣列比較元素的方式,但在實作上卻有一些不一樣的地方, Comparable 是一個接口,只定義了一個名為 compareTo 的方法,傳回 int ,Comparator 也是一個接口,定義了一個傳入 2 個參數,傳回 int 的 compare 方法,這兩者都是用來對集合排序元素, Difference Between Comparator and Comparable in Java 提供這兩種接口應用方式,本篇增加了範例,並透過單元測試來驗證產出結果。
public interface Comparable<T> {
public int compareTo(T o);
}
大於 o 傳回 1 。
等於 o 傳回 0 。
小於 o 傳回 -1 。
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
o1 大於 o2 傳回 1 。
o1 等於 o2 傳回 0 。
o1 小於 o2 傳回 -1 。
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- comparator
| +- DifferenceComparableComparatorTest.java
單元測試
Difference Between Comparable and Comparator in Java 提供集合或陣列排序元素等操作。
Fruit
Difference Between Comparable and Comparator 建立 Fruit 類別,覆寫 toString ,定義屬性和方法,用來建立一個物件。
@NoArgsConstructor
@Getter
@Setter
@Builder
public static class Fruit implements Comparable<Fruit> {
private String name;
private double quantity;
private int type;
public Fruit(String name, double quantity, int type) {
this.name = name;
this.quantity = quantity;
this.type = type;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
builder.appendSuper(super.toString());
builder.append("name", name);
builder.append("quantity", quantity);
builder.append("type", type);
return builder.toString();
}
@Override
public int compareTo(Fruit o) {
return Double.compare(this.quantity, o.quantity);
}
}
compareTo
Difference Between Comparable and Comparator 建立集合,比對字串或數字,由小到大排序。
@NoArgsConstructor
@Getter
@Setter
@Builder
public static class Fruit implements Comparable<Fruit> {
private String name;
private double quantity;
private int type;
public Fruit(String name, double quantity, int type) {
this.name = name;
this.quantity = quantity;
this.type = type;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
builder.appendSuper(super.toString());
builder.append("name", name);
builder.append("quantity", quantity);
builder.append("type", type);
return builder.toString();
}
@Override
public int compareTo(Fruit o) {
return Double.compare(this.quantity, o.quantity);
}
}
@Test
public void compareTo() {
List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1));
System.out.println(list);
Collections.sort(list);
System.out.println(list);
assertEquals(-1d, list.get(0).getQuantity(), 2);
assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Mango","quantity":-1.0,"type":3}, {"name":"Peach","quantity":3.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Mango","quantity":-1.0,"type":3}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Peach","quantity":3.0,"type":1}]
arrayCompareTo
Difference Between Comparable and Comparator 建立陣列,比對字串或數字,由小到大排序。
@Test
public void arrayCompareTo() {
Fruit[] array = new Fruit[] { new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1) };
System.out.println(Arrays.toString(array));
Arrays.sort(array);
System.out.println(Arrays.toString(array));
assertEquals(-1d, array[0].getQuantity(), 2);
assertEquals(Double.MAX_VALUE, array[1].getQuantity(), 2);
}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Mango","quantity":-1.0,"type":3}, {"name":"Peach","quantity":3.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Mango","quantity":-1.0,"type":3}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Peach","quantity":3.0,"type":1}]
compare
Difference Between Comparable and Comparator 建立集合,比對字串或數字,由小到大排序。
@Test
public void compare() {
List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Peach", -1d, 1),
new Fruit("Orange", 2, 1));
System.out.println(list);
Comparator<Fruit> quantityComparator = (o, o2) -> Double.compare(o.quantity, o2.quantity);
Collections.sort(list, quantityComparator);
System.out.println(list);
assertEquals("Peach", list.get(0).getName());
assertEquals("Orange", list.get(1).getName());
assertEquals("Mango", list.get(2).getName());
}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Peach","quantity":-1.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Peach","quantity":-1.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}]
arrayCompare
Difference Between Comparator and Comparable 建立陣列,比對字串或數字,由小到大排序。
@Test
public void arrayCompare() {
Fruit[] array = new Fruit[] { new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Peach", -1d, 1),
new Fruit("Orange", 2, 1) };
System.out.println(Arrays.toString(array));
Comparator<Fruit> quantityComparator = (o, o2) -> Double.compare(o.quantity, o2.quantity);
Arrays.sort(array, quantityComparator);
System.out.println(Arrays.toString(array));
assertEquals("Peach", array[0].getName());
assertEquals("Orange", array[1].getName());
assertEquals("Mango", array[2].getName());
}
[{"name":"Mango","quantity":1.7976931348623157E308,"type":1}, {"name":"Peach","quantity":-1.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}]
[{"name":"Peach","quantity":-1.0,"type":1}, {"name":"Orange","quantity":2.0,"type":1}, {"name":"Mango","quantity":1.7976931348623157E308,"type":1}]
DifferenceComparableComparatorTest.java
Difference Between Comparator and Comparable 新增單元測試,驗證 Difference Between Comparable and Comparator Interface in Java 是否符合預期。
package org.ruoxue.java_147.comparator;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Test;
import org.ruoxue.java_147.collection.ComparableVSComparatorTest.Fruit;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
public class DifferenceComparableComparatorTest {
@NoArgsConstructor
@Getter
@Setter
@Builder
public static class Fruit implements Comparable<Fruit> {
private String name;
private double quantity;
private int type;
public Fruit(String name, double quantity, int type) {
this.name = name;
this.quantity = quantity;
this.type = type;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
builder.appendSuper(super.toString());
builder.append("name", name);
builder.append("quantity", quantity);
builder.append("type", type);
return builder.toString();
}
@Override
public int compareTo(Fruit o) {
return Double.compare(this.quantity, o.quantity);
}
}
@Test
public void compareTo() {
List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1));
System.out.println(list);
Collections.sort(list);
System.out.println(list);
assertEquals(-1d, list.get(0).getQuantity(), 2);
assertEquals(Double.MAX_VALUE, list.get(1).getQuantity(), 2);
}
@Test
public void arrayCompareTo() {
Fruit[] array = new Fruit[] { new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Mango", -1, 3),
new Fruit("Peach", 3, 1), new Fruit("Orange", 2, 1) };
System.out.println(Arrays.toString(array));
Arrays.sort(array);
System.out.println(Arrays.toString(array));
assertEquals(-1d, array[0].getQuantity(), 2);
assertEquals(Double.MAX_VALUE, array[1].getQuantity(), 2);
}
@Test
public void compare() {
List<Fruit> list = Arrays.asList(new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Peach", -1d, 1),
new Fruit("Orange", 2, 1));
System.out.println(list);
Comparator<Fruit> quantityComparator = (o, o2) -> Double.compare(o.quantity, o2.quantity);
Collections.sort(list, quantityComparator);
System.out.println(list);
assertEquals("Peach", list.get(0).getName());
assertEquals("Orange", list.get(1).getName());
assertEquals("Mango", list.get(2).getName());
}
@Test
public void arrayCompare() {
Fruit[] array = new Fruit[] { new Fruit("Mango", Double.MAX_VALUE, 1), new Fruit("Peach", -1d, 1),
new Fruit("Orange", 2, 1) };
System.out.println(Arrays.toString(array));
Comparator<Fruit> quantityComparator = (o, o2) -> Double.compare(o.quantity, o2.quantity);
Arrays.sort(array, quantityComparator);
System.out.println(Arrays.toString(array));
assertEquals("Peach", array[0].getName());
assertEquals("Orange", array[1].getName());
assertEquals("Mango", array[2].getName());
}
}
心得分享
Difference Between Comparable and Comparator Interface in Java 的區別:
Comparable Interface | Comparator Interface |
---|---|
宣告的方法是 compareTo | 宣告的方法是 compare |
提供了單一的排序序列 | 提供了多種排序順序 |
影響原類別,即實際類別被修改 | 不影響原類別,即不修改實際類別 |
存在於 java.lang 中 | 存在於 java.util 中 |
使用 Collections.sort(List) 方法對 Comparable 類型的元素進行排序 | 使用 Collections.sort(List, Comparator) 方法對 Comparator 類型的元素進行排序 |
使用 Arrays.sort(Array) 方法對 Comparable 類型的元素進行排序 | 使用 Arrays.sort(Array, Comparator) 方法對 Comparator 類型的元素進行排序 |