跳轉到內容

比較物件

75% developed
來自 Wikibooks,開放世界中的開放書籍

導航 聚合 主題:v  d  e )

在 Java 中,我們可以區分兩種型別的等式。

  • 物件引用等式:當兩個物件引用指向同一個物件時。
  • 物件值等式:當兩個獨立的物件恰好具有相同的數值/狀態時。

如果兩個物件在引用方面相等,它們在值方面也相等。

比較引用等式

[編輯 | 編輯原始碼]

== 運算子可用於檢查兩個物件引用是否指向同一個物件。

Example 程式碼部分 5.19:引用等式。
if (objRef1 == objRef2) {
    // The two object references point to the same object
}

比較值等式

[編輯 | 編輯原始碼]

為了能夠比較同一個類的兩個 Java 物件,boolean equals(Object obj) 方法必須被該類覆蓋並實現。

實現者決定哪些值必須相等才能認為兩個物件相等。例如,在下面的類中,nameaddress 必須相等,但 description 不必。

Computer code 程式碼清單 5.5:Customer.java
public class Customer {
    private String name;
    private String address;
    private String description;
    // ...
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (obj == null) {
            return false;
        } else if (obj instanceof Customer cust) {
            if ( ((cust.getName() == null && name == null) || cust.getName().equals(name)) 
              && ((cust.getAddress() == null && address == null) || cust.getAddress().equals(address))
               ) {
                return true;
            }
        }
        return false;
    }

}

equals() 方法被覆蓋後,來自同一個類的兩個物件可以這樣比較

Example 程式碼部分 5.20:方法用法。
Customer cust1 = new Customer();
Customer cust2 = new Customer();
//...
if (cust1.equals(cust2)) {
    // Two Customers are equal, by name and address
}

注意,相等的物件必須具有相等的雜湊碼。因此,當覆蓋 equals 方法時,您也必須覆蓋 hashCode 方法。未能做到這一點將違反 hashCode 方法的一般約定,並且任何使用雜湊碼的類(例如 HashMap)將無法正常執行。

排序/排序

[編輯 | 編輯原始碼]

在 Java 中,有幾種現有的方法已經對來自任何類的物件進行了排序,例如 Collections.sort(List<T> list)。但是,Java 需要知道兩個物件之間的比較規則。因此,當您定義一個新類並希望您的類的物件可排序時,您必須實現 Comparable 並重新定義 compareTo(Object obj) 方法。

int compareTo(T o)
比較兩個物件並返回一個整數
  • 負整數表示當前物件在自然排序中位於引數物件之前。
  • 零表示當前物件和引數物件相等。
  • 正整數表示當前物件在自然排序中位於引數物件之後。

假設名稱比地址更重要,而描述被忽略。

Computer code 程式碼清單 5.6:SortableCustomer.java
public class SortableCustomer implements Comparable<SortableCustomer> {
    private String name;
    private String address;
    private String description;
    // ...
    public int compareTo(SortableCustomer anotherCustomer) {
        if (name.compareTo(anotherCustomer.getName()) == 0) {
            return address.compareTo(anotherCustomer.getAddress());
        } else {
            return name.compareTo(anotherCustomer.getName());
        }
    }

}

實現此介面的物件可以用作排序地圖中的鍵或排序集中的元素,而無需指定比較器。

如果且僅當對於類 C 的每個 e1 和 e2,e1.compareTo((Object) e2) == 0e1.equals((Object) e2) 具有相同的布林值,則類 C 的自然排序被認為與 equals 一致。注意,null 不是任何類的例項,並且 e.compareTo(null) 應該丟擲一個 NullPointerException,即使 e.equals(null) 返回 false。

強烈建議(但不是必需)自然排序與 equals 一致。這是因為沒有顯式比較器的排序集(和排序地圖)在與自然排序與 equals 不一致的元素(或鍵)一起使用時,行為“奇怪”。特別是,這樣的排序集(或排序地圖)違反了集合(或地圖)的一般約定,集合(或地圖)的一般約定是在 equals 方法的定義中定義的。

更改排序/排序

[編輯 | 編輯原始碼]

有時我們可能希望更改來自同一個類的物件集合的排序方式。我們可能希望按降序或升序排序。我們可能希望按nameaddress 排序。

我們需要為每種排序方式建立一個類。它必須實現 Comparator 介面。

從 Java 5.0 開始,Comparator 介面是泛型的;這意味著當您實現它時,您可以指定比較器可以比較的物件型別。

Computer code 程式碼清單 5.7:CustomerComparator.java
public class CustomerComparator implements Comparator<Customer> {
    public int compare(Customer cust1, Customer cust2) {
        return cust1.getName().compareTo(cust2.getName());
    }
}

上面的類然後可以與 SortedSet 或其他支援排序的集合關聯。

Example 程式碼部分 5.21:比較器用法。
Collection<Customer> orderedCustomers = new TreeSet<Customer>(new CustomerComparator());

使用迭代器,可以按name 排序的順序遍歷 orderedCustomers 集合。

列表可以透過 Collectionssort 方法進行排序。

Example 程式碼部分 5.22:自定義比較。
java.util.Collections.sort(custList, new CustomerComparator());

根據指定比較器引起的順序,對指定列表進行排序。列表中的所有元素都必須使用指定的比較器相互比較。

物件陣列也可以在 Comparator 的幫助下進行排序。

Example 程式碼部分 5.23:陣列排序。
SortableCustomer[] customerArray;
//...
java.util.Arrays.sort(customerArray, new CustomerComparator());

根據指定比較器引起的順序,對指定的 Customer 物件陣列(customerArray)進行排序。陣列中的所有元素都必須使用指定的比較器相互比較。


Clipboard

待辦事項
新增一些類似於變數 中的練習


華夏公益教科書