A. java中,comparator與comparable有什麼不同
在Java的集合框架中,`Comparable`和`Comparator`這兩個術語經常被提及,它們在比較對象時扮演著關鍵角色。本文旨在深入解析這兩種機制,以解答「Java中,`Comparator`與`Comparable`有什麼不同?」這一問題。
`Comparable`是一個介面,它要求類實現一個名為`compareTo`的方法,用於比較實例之間的相對順序。實現`Comparable`介面的類必須重寫`compareTo`方法,以便定義對象間的比較邏輯。例如,可以定義一個`Person`類,通過比較年齡來實現對象間的排序。下面是一個簡單的示例,展示了如何實現`Comparable`介面來比較年齡大小。
java
class Person implements Comparable {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(20);
Person p2 = new Person();
p2.setAge(30);
List list = new ArrayList>();
list.add(p1);
list.add(p2);
Collections.sort(list);
System.out.println(list.get(0).getAge() < list.get(1).getAge()); // 輸出:true
}
}
`Comparator`是一個介面,它提供了比`Comparable`更加靈活的比較方式,允許在不修改原有類的情況下定義比較邏輯。`Comparator`的核心方法是`compare`,用於比較兩個對象之間的順序。下面是一個示例,展示了如何為`Person`類定義一個自定義的比較器,用於比較年齡大小。
java
class PersonalComparator implements Comparator {
@Override
public int compare(Person p1, Person p2) {
return Integer.compare(p1.getAge(), p2.getAge());
}
}
public class Main {
public static void main(String[] args) {
List list = new ArrayList>();
list.add(new Person());
list.get(0).setAge(20);
list.add(new Person());
list.get(1).setAge(30);
list.sort(new PersonalComparator());
System.out.println(list.get(0).getAge() < list.get(1).getAge()); // 輸出:true
}
}
在實現排序邏輯時,`Comparator`允許我們更加靈活地控制對象間的比較,而無需修改對象本身的類。例如,我們可以使用`Collections.sort()`方法,傳入一個`Comparator`對象來對集合進行排序。
總結而言,`Comparable`介面提供了類內比較功能,適用於實現對象間的自然比較邏輯;而`Comparator`介面則提供了更加靈活的比較機制,允許在不修改對象類的情況下實現復雜比較規則。理解這兩個機制的不同應用場景,有助於在Java編程中更有效地管理數據的排序與比較。
B. java中Comparable和Comparator兩種比較器的區別
Comparable和Comparator介面都是為了對類進行比較,眾所周知,諸如Integer,double等基本數據類型,java可以對他們進行比較,而對於類的比較,需要人工定義比較用到的欄位比較邏輯。可以把Comparable理解為內部比較器,而Comparator是外部比較器,基本的寫法如下:
class Apple implements Comparable<Apple>{
int id;
double price;
public Apple(int id, double price) {
this.id = id;
this.price = price;
}
public int compareTo(Apple o) {
//return Double.compare(this.getPrice(),o.getPrice());
if (Math.abs(this.price-o.price)<0.001)
return 0;
else
return (o.price-this.price)>0?1:-1;
}
@Override
public String toString() {
return "Apple{" +
"id=" + id +
", price=" + price +
'}';
}
}
class AESComparator implements Comparator<Apple>{
public int compare(Apple o1, Apple o2) {
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else{
return (o1.price-o2.price)>0?1:-1;
}
}
}
實現了Comparable介面的類需要實現compareTo()方法,傳入一個外部參數進行比對,實現了Comparator介面的方法需要實現compare()方法,對外部傳入的兩個類進行比較,從而讓外部方法在比較時調用。
兩者的區別是實現Comparator介面代碼更加靈活,可以定義某個類的多個比較器,從而在排序時根據實際場景自由調用,而Comparable介面實現後便不能改動。兩種介面的調用方式如下:
class AESComparator implements Comparator<Apple>{
public int compare(Apple o1, Apple o2) {
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else{
return (o1.price-o2.price)>0?1:-1;
}
}
}
class DESComparator implements Comparator<Apple>{
public int compare(Apple o1, Apple o2) {
if (Math.abs(o1.price-o2.price)<0.001)
return 0;
else {
return (o1.price-o2.price)>0?-1:1;
}
}
}
public static void main(String[] args) {
Apple apple1 = new Apple(1,4.8);
Apple apple2 = new Apple(2,5.9);
Apple apple3 = new Apple(3,8.5);
List<Apple> list = new ArrayList<Apple>();
list.add(apple1);
list.add(apple3);
list.add(apple2);
System.out.println("Comparable==========");
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list);
System.out.printf("this list of apples: %s\n",list);
System.out.println("Comparator==========");
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list,new DESComparator());
System.out.printf("this list of apples: %s\n",list);
Collections.sort(list,new AESComparator());
System.out.printf("this list of apples: %s\n",list);
}
}
上述代碼存在的問題,不能在比較器中進行double類型的減法操作,因為對於值比較大的double,減法操作容易導致值的溢出,java7對每一種包裝類型的比較新增了compare()方法,改造後的代碼如下:
class Apple implements Comparable<Apple>{
int id;
double price;
public Apple(int id, double price) {
this.id = id;
this.price = price;
}
public int compareTo(Apple o) {
return Double.compare(this.price,o.price);
}
@Override
public String toString() {
return "Apple{" +
"id=" + id +
", price=" + price +
'}';
}
}
class AESComparator implements Comparator<Apple>{
public int compare(Apple o1, Apple o2) {
return Double.compare(o1.price,o2.price);
}
}
class DESComparator implements Comparator<Apple>{
public int compare(Apple o1, Apple o2) {
return Double.compare(o2.price,o1.price);
}
}
查看Double.compare的源碼如下
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}