在Effective Java中的第九条说:覆盖equals总要覆盖hashCode。
“一个很常见的错误根源在于没有覆盖hashCode方法,在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。”
以下约定内容摘自Object规范[JavaSE6]:
1. 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,
必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2.
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
3. 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
显然,如果没有覆盖hashCode,就会违反第二条关键约定。
以上为理论部分,以下为实际实践的尝试,显示hashCode的作用:
首先生成一个简单的Box类:
public final class Box {
private int length;
private int width;
private int heigth;
public Box(){
}
public Box(int length, int width, int heigth){
this.length = length;
this.width = width;
this.heigth = heigth;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeigth() {
return heigth;
}
public void setHeigth(int heigth) {
this.heigth = heigth;
}
@Override
//重写equals方法。
public boolean equals(Object o){
if(o == this){
return true;
}else if(!(o instanceof Box)){
return false;
}else {
Box boxtmp = (Box) o;
return boxtmp.heigth == this.heigth
&& boxtmp.width == this.width
&& boxtmp.length == this.length;
}
}
}
类Box中重写了equals方法。
然后写一个测试类:
iimport java.util.HashMap;
public class HashCodeAndEqualTest {
public static void main(String[] args) {
Map<Box, Integer> map = new HashMap<Box, Integer>();
Box a = new Box(1,2,3);
Box b = new Box(1,2,3);
System.out.println("a == b :"+(a == b));
System.out.println("a .equals(b):"+a .equals(b));
map.put(a, 1);
System.out.println(map.get(a));
System.out.println(map.get(b));
}
}
输出结果:
引用
a == b :false
a .equals(b):true
1
null
既然a.equals(b)都已经为true了,那为什么map.get(b)的返回值为null呢?map.get(b)的预期值应该和map.get(a)相等的,下面再在Box类中重写一个父类方法:hashCode():
@Override
public int hashCode(){
int result = 0;
result = result * 31 + length;
result = result * 31 + heigth;
result = result * 31 + width;
return result;
}
然后再运行测试类,结果如下:
a == b :false
a .equals(b):true
1
1
为什么这次map.get(b) 和map.get(a)中的值相等了呢?这是因为重写了Box类中的hashCode方法,符合了第二天规定,
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
这样对象a和对象b的hash值是相等的。通俗一点儿讲, 如果a.hashCode () = b.hashCode()而且 a.euqals(b) (或 a==b) , 那么根据HashMap的算法,二者在同一个位置的,即HashMap认为只有符合以上条件,才认为a,和b是为同一key。
再深一点儿,可以参考HashMap中的get和put方法的实现,便可一探究竟。
HashMap中的get方法:
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
HashMap中的put方法:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
这一句已经大致解释了刚才的情况,更深一点儿可以探究一下hash算法的实现,挺有意思,不过时间有限,就先写到这里了~~
分享到:
相关推荐
在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...
在Java编程中,当我们重写`equals()`方法时,通常也需要重写`hashCode()`方法。这是因为`equals()`和`hashCode()`方法在Java集合框架中扮演着重要的角色,特别是在使用`HashMap`、`HashSet`等基于哈希表的集合类时。...
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
在Java编程语言中,`equals()`和`hashCode()`方法是两个至关重要的概念,它们与对象的比较和哈希表操作紧密相关。理解这两个方法的工作原理及其契约是成为一名熟练的Java开发者所必需的。 首先,`equals()`方法是...
总的来说,理解并正确地重写 `equals()` 和 `hashCode()` 方法是Java编程中的基础技能,它有助于确保对象的比较和集合操作的正确性。在开发过程中,要时刻注意这两个方法的正确实现,以提高代码质量和可维护性。
深入解析Java对象的equals()和hashCode()的使用 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。在多数情况下,这两个函数是不用考虑的,直接使用它们...
本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...
2. **hashCode方法**:当覆写`equals`时,必须同时覆写`hashCode`,以保持哈希表的正确性。 3. **toString方法**:为每个类提供一个有意义的字符串表示,方便调试和日志记录。 4. **clone方法**:`clone`方法的覆写...
- Item9:当覆盖equals时,必须同时覆盖hashcode,以保持哈希表的行为一致性。 - Item10:toString方法应返回对象状态的简洁表示,便于调试和日志记录。 - Item11:谨慎覆盖clone方法,因为它涉及到对象的深拷贝...
在Java编程语言中,`hashCode()`和`equals()`方法是对象身份验证的关键组成部分,它们主要用于对象的比较和哈希表(如HashMap、HashSet等)的操作。理解这两个方法的工作原理对于编写高效和可靠的代码至关重要。 ...
### Java中`hashCode()`与`equals()`方法详解 #### 前言 在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将...
在Java编程语言中,`equals()`和`hashCode()`方法是对象的基本组成部分,它们主要用于对象的比较和存储。这两个方法在`java.lang.Object`类中定义,因此所有的Java类都默认继承了这两个方法。然而,根据具体的应用...
本文将详细介绍 hashCode() 和 equals() 的本质区别和联系,并探讨在创建 Java 类时如何定义这些方法。 hashCode() 方法 hashCode() 方法是 Object 类中的一个方法,它返回对象的哈希码值。哈希码值是一个整数,它...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的概念,尤其是在处理对象比较和哈希表(如 `HashMap` 和 `HashSet`)时。`equals()` 方法用于判断两个对象是否相等,而 `hashCode()` 方法则用于...
equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.
在Java编程中,`equals()`和`hashCode()`方法是Object类中的两个重要方法,它们在比较和处理对象时起着至关重要的作用。`equals()`方法用于判断两个对象是否相等,而`hashCode()`方法则与对象在哈希表中的存储位置...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的成员,尤其是在处理对象比较和集合操作时。这两个方法通常与`Object`类中的默认实现相关联,但为了在实际开发中实现正确的对象比较和哈希表操作...
在Java编程语言中,`equals()`, `hashCode()` 和 `toString()` 是三个非常重要的方法,它们主要用于对象的比较、哈希存储以及打印对象信息。这三个方法是Java对象的基础特性,对于理解和开发高质量的Java程序至关...
- **覆盖 equals() 和 hashCode()**:当重写`equals()`时,必须同时重写`hashCode()`以保持一致性。 4. **异常处理** - **异常不应用于控制流**:异常应被视为异常情况的信号,而不是正常的程序流程控制手段。 -...