Java中如何比較對象 詳解equals實現

Java中比較對象需重寫equals()和hashcode(),1. 使用==比較對象引用地址;2. 重寫equals()根據屬性判斷邏輯相等性;3. 同時重寫hashcode()保證哈希碼一致以支持hashmap等結構;4. 可使用objects.equals()和objects.hash()簡化實現并避免空指針;5. 還可通過comparable或comparator接口進行排序比較。

Java中如何比較對象 詳解equals實現

Java中比較對象,核心在于理解equals()方法和hashCode()方法。簡單來說,equals()用于判斷兩個對象在邏輯上是否相等,而hashCode()則為對象生成一個哈希碼,用于在哈希表等數據結構中快速查找對象。兩者密切相關,需要同時重寫以保證一致性。

Java中如何比較對象 詳解equals實現

解決方案

Java中如何比較對象 詳解equals實現

在Java中比較對象,通常涉及以下幾個方面:

立即學習Java免費學習筆記(深入)”;

Java中如何比較對象 詳解equals實現

  1. == 運算符 比較的是兩個對象的引用是否指向內存中的同一個地址。如果兩個對象是同一個實例,==返回true,否則返回false。這是一種淺比較。

  2. equals() 方法: equals()方法默認行為與==相同,即比較對象的引用。但通常需要重寫equals()方法,以便根據對象的屬性值來判斷兩個對象是否邏輯相等。例如,兩個Person對象,如果他們的name和age屬性相同,則認為這兩個對象相等。

    @Override public boolean equals(Object obj) {     if (this == obj) {         return true;     }     if (obj == NULL || getClass() != obj.getClass()) {         return false;     }     Person person = (Person) obj;     return age == person.age && Objects.equals(name, person.name); }
  3. hashCode() 方法: 如果重寫了equals()方法,強烈建議同時重寫hashCode()方法。hashCode()方法返回對象的哈希碼,用于在哈希表(如HashMap、HashSet)中快速定位對象。如果兩個對象equals()返回true,那么它們的hashCode()必須相等。反之,如果兩個對象的hashCode()相等,equals()不一定返回true(存在哈希沖突)。

    @Override public int hashCode() {     return Objects.hash(name, age); }
  4. Objects.equals() 和 Objects.hash(): Java 7 引入了Objects類,提供了equals()和hash()方法,可以簡化equals()和hashCode()的實現,并避免空指針異常。

  5. 為什么要同時重寫 equals() 和 hashCode()? 考慮使用HashMap的情況。HashMap通過鍵的哈希碼來存儲和查找鍵值對。如果只重寫了equals()方法,而沒有重寫hashCode()方法,那么即使兩個對象equals()返回true,它們的哈希碼可能不同,導致HashMap無法正確找到對應的鍵值對。舉個例子,你new了兩個Person對象,name和age一樣,equals返回true,但是沒重寫hashCode,那么hashcode不一樣,在HashMap中會被認為是兩個不同的key。

如何正確重寫equals方法?

重寫equals()方法需要遵循一些約定:

  • 自反性: 對于任何非空對象 x,x.equals(x) 必須返回 true。
  • 對稱性: 對于任何非空對象 x 和 y,如果 x.equals(y) 返回 true,則 y.equals(x) 必須返回 true。
  • 傳遞性: 對于任何非空對象 x、y 和 z,如果 x.equals(y) 返回 true 且 y.equals(z) 返回 true,則 x.equals(z) 必須返回 true。
  • 一致性: 對于任何非空對象 x 和 y,如果對象上 equals 比較中所用的信息沒有修改,則多次調用 x.equals(y) 始終返回 true 或始終返回 false。
  • 非空性: 對于任何非空對象 x,x.equals(null) 必須返回 false。

一個安全的equals()實現通常包括以下步驟:

  1. 使用 == 檢查是否為同一個對象。
  2. 檢查是否為 null。
  3. 檢查是否為相同的類。
  4. 將對象強制轉換為相應的類型。
  5. 比較所有重要的屬性。

為什么需要使用Objects.equals() 和 Objects.hash()?

使用Objects.equals()和Objects.hash()可以簡化代碼,并避免空指針異常。Objects.equals()方法可以安全地比較兩個對象,即使其中一個對象為null,也不會拋出異常。Objects.hash()方法可以接受多個參數,并生成一個哈希碼,方便快捷。

例如:

@Override public boolean equals(Object o) {     if (this == o) return true;     if (o == null || getClass() != o.getClass()) return false;     Person person = (Person) o;     return age == person.age &&            Objects.equals(name, person.name) &&            Objects.equals(address, person.address); }  @Override public int hashCode() {     return Objects.hash(name, age, address); }

除了equals和hashCode,還有其他比較對象的方式嗎?

是的,除了equals()和hashCode(),還有其他比較對象的方式:

  1. Comparable 接口: 如果需要對對象進行排序,可以實現Comparable接口,并重寫compareTo()方法。compareTo()方法返回一個整數,表示當前對象與另一個對象的比較結果。正數表示大于,負數表示小于,零表示相等。

    public class Person implements Comparable<Person> {     private String name;     private int age;      @Override     public int compareTo(Person other) {         // 先按年齡排序,再按姓名排序         int ageComparison = Integer.compare(this.age, other.age);         if (ageComparison != 0) {             return ageComparison;         }         return this.name.compareTo(other.name);     } }
  2. Comparator 接口: 如果不想修改對象本身,或者需要提供多種排序方式,可以使用Comparator接口。Comparator是一個獨立的比較器,可以定義不同的比較規則。

    Comparator<Person> nameComparator = (p1, p2) -> p1.getName().compareTo(p2.getName());
  3. 第三方庫: 例如apache Commons Lang庫中的EqualsBuilder和HashCodeBuilder,可以更方便地實現equals()和hashCode()方法。guava庫也提供了類似的工具

  4. Serialization: 通過序列化和反序列化對象,然后比較序列化后的字節數組。這種方法通常用于比較復雜對象,但性能較低。

選擇哪種比較方式取決于具體的需求。如果只是判斷對象是否相等,重寫equals()和hashCode()方法即可。如果需要對對象進行排序,可以實現Comparable或使用Comparator。

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享