您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。