# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。