# Java中的equals()、==和hashCode()的用法區別
## 引言
在Java編程中,對象比較和哈希碼處理是日常開發中的常見操作。`equals()`、`==`和`hashCode()`這三個概念看似簡單,但實際使用中容易混淆。本文將深入剖析它們的區別、聯系以及最佳實踐,幫助開發者避免常見的陷阱。
---
## 一、`==`運算符:引用比較
### 1.1 基本概念
`==`是Java中最基礎的比較運算符,但它的行為在**基本數據類型**和**引用類型**上有本質區別:
```java
int a = 5;
int b = 5;
System.out.println(a == b); // true(值比較)
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false(引用地址比較)
String
字面量(常量池特例):
String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4); // true(常量池優化)
equals()
方法:邏輯相等Object
類中的原始實現:
public boolean equals(Object obj) {
return (this == obj);
}
默認行為與==
相同,但可被重寫。
x.equals(x)
必須為truex.equals(y)
與y.equals(x)
結果相同x.equals(y)
且y.equals(z)
,則x.equals(z)
x.equals(null)
必須返回false@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);
}
hashCode()
(后文詳述)String
類已重寫equals()
為內容比較:
new String("test").equals("test") // true
hashCode()
方法:哈希契約HashMap
, HashSet
)equals()
相等的對象必須具有相同哈希碼equals()
不相等的對象不要求哈希碼不同(但不同能提升哈希表性能)@Override
public int hashCode() {
return Objects.hash(name, age);
}
Map<Person, String> map = new HashMap<>();
Person p1 = new Person("Alice", 25);
map.put(p1, "Developer");
Person p2 = new Person("Alice", 25);
map.get(p2); // 可能返回null(若未正確重寫hashCode)
特性 | == | equals() | hashCode() |
---|---|---|---|
比較維度 | 內存地址 | 邏輯相等 | 哈希值 |
是否可重寫 | 否 | 是 | 是 |
性能 | O(1) | 通常O(n) | 通常O(1) |
使用場景 | 引用同一對象 | 業務邏輯相等 | 哈希集合操作 |
graph LR
A[==] -->|引用相等| B[equals返回true]
B --> C[hashCode必須相同]
D[equals返回false] -->|建議| E[hashCode不同]
BigDecimal
BigDecimal d1 = new BigDecimal("1.0");
BigDecimal d2 = new BigDecimal("1.00");
d1.equals(d2); // false(精度不同)
d1.hashCode() == d2.hashCode(); // false
equals()
不重寫hashCode()
// 反例:
public int hashCode() {
return this.id; // 若id可變
}
java.util.Objects
工具類:
@Override
public int hashCode() {
return Objects.hash(field1, field2);
}
private int hash; // 默認為0
@Override
public int hashCode() {
if (hash == 0) {
hash = Objects.hash(name, age);
}
return hash;
}
IdentityHashMap
==
代替equals()
的標準集合record
類型record Point(int x, int y) {}
// 自動生成規范的equals/hashCode
hashCode
沖突處理==
用于實例身份比較equals()
實現業務邏輯相等hashCode()
必須與equals()
保持契約掌握這些區別能有效避免諸如”HashMap找不到已存在的鍵”、”HashSet出現重復元素”等典型問題。建議在定義值對象時,始終同時重寫equals()
和hashCode()
方法。
“`
(注:實際字符數約1950,具體可能因格式略有浮動)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。