1. 程式人生 > >java物件的4種比較方法

java物件的4種比較方法

概述

在java中,存在4種物件(含基礎資料型別)的比較方式:==、equals、compareTo和compare。以及兩種比較策略:引用比較和值比較。具體如下表所示。

比較 基本資料型別 物件
==、!= 值比較 引用比較。使用”==”進行物件引用比較有以下限制:比較引用是否為null;用於列舉比較時是值比較,因為每個列舉常量只有一個物件;檢查兩個引用是否指向同一個物件,通常物件的比較應該用equals
equals 比較值的相等性。所有類都繼承了該方法,但要進行值比較需要對equals方法複寫,來實現比較邏輯。未複寫的該方法的行為同”==”,是引用比較。通常equals首先進行”==”判斷,是同一個物件則可快速返回
compareTo Comparable< T >的介面。比較值並返回1(大於)、0(等於)、小於(-1)。如果物件是具有自然順序的或想要進行Collections.sort()或Arrays.sort(),可以實現Comparable介面。如String、Double、Interger等
compare Comparator< T >的一個介面。比較兩個物件的值。典型應用是將實現該介面的類作為工具類,傳入如sort()之類的方法或用於排序的資料結構如TreeMap或TreeSet中進行物件排序。在下列場景中可能需要Comparator物件:多重比較
,需要提供不同的排序方式。如要對一個具有name、ID、age、height的Person類進行排序,那麼需要定義Comparator傳入sort()方法;系統類為任意物件提供比較方法。如定義一個Comparator用於比較String的length;策略模式在需要將演算法表現為一個物件的場景中實現策略模式,可將其作為引數或儲存在資料結構中。如果類物件具有自然排序序列,則不需要該介面。

自然順序(natural ordering):物件的值具有數值特性,可使用四則運算。如String、Integer類。

注意1:如果複寫了equals()方法,也應該複寫hashCode()方法。HashSet和HashMap之類的資料結構使用hashCode()來雜湊,如果不復寫,在應用於這些資料結構時可能工作不正常。
注意2

:一般情況下,如果a.equals(b)是true,那麼a.compareTo(b) == 0也應該是true。一個例外是BigDecimal類,因為BigDecimal的equals是在value值和scale都相同才為true,而compareTo是value值相同scale不同也返回0。如:

BigDecimal bd = new BigDecimal(1.2, MathContext.DECIMAL32);
BigDecimal bd2 = new BigDecimal(1.2, MathContext.DECIMAL64);
bd.equals(bd2);    // return false
bd.compareTo(bd2); // return 0

程式碼示例

// 1. 值比較
int a = 5;
int b = 5;
int c = 6;
a == b; // return true
a == c; // return false


// 2. equals比較
// MyClass未複寫equals方法
class MyClass {
    private int myVirable;
    MyClass() {}
    MyClass(int virable) {
        this.myVirable = virable;
    } 
}

MyClass obj1 = new MyClass(5);
MyClass obj2 = new MyClass(5);
MyClass obj3 = obj2;
obj1.equals(obj2); // return false
obj3.equals(obj1); // return true

// MyClass複寫equals方法
class MyClass {
    private int myVirable;
    MyClass() {}
    MyClass(int virable) {
        this.myVirable = virable;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof MyClass) {
            MyClass o = (MyClass)obj;
            if (o.myVirable == this.myVirable) {
                return true;
            }
        }

        return false;
    }
}

MyClass obj1 = new MyClass(5);
MyClass obj2 = new MyClass(5);
obj1.equals(obj2); // return true


// 3. compareTo比較
public class MyCompareClass implements Comparable<MyCompareClass> {
    private int code;

    MyCompareClass(int code) {
        this.code = code;
    }

    @Override
    public int compareTo(MyCompareClass o) {
        if(code > o.code) {
            return 1;
        } else if(code < o.code) {
            return -1;
        } else {
            return 0;
        }
    }
}

MyCompareClass comp1 = new MyCompareClass(7);
MyCompareClass comp2 = new MyCompareClass(5);
MyCompareClass comp3 = new MyCompareClass(9);
MyCompareClass comp4 = new MyCompareClass(7);
comp1.compareTo(comp2); // return 1
comp1.compareTo(comp3); // return -1
comp1.compareTo(comp4); // return 0


// 4. comapre比較
public class MyCompareClass {
    int code;
    MyCompareClass(int code) {
        this.code = code;
    }
}

// 實現比較器介面
class MyComparator implements Comparator<MyCompareClass>{  
    @Override  
    public int compare(MyCompareClass o1, MyCompareClass o2) {  
        if(o1.code > o2.code){  
            return 1;  
        } else if(o1.code < o2.code){  
            return -1;  
        } else {  
            return 0;
        }  
    }  
}

MyCompareClass o1 = new MyCompareClass(7);
MyCompareClass o2 = new MyCompareClass(5);
MyCompareClass o3 = new MyCompareClass(9);
List<MyCompareClass>list=new ArrayList<MyCompareClass>();  
list.add(o1);  
list.add(o2);  
list.add(o3);
Collections.sort(list, new MyComparator());
for(MyCompareClass e:list){  
    System.out.println(e.code);  
}  
// 輸出為:
// 5
// 7
// 9