JSL规定,调用两个Equals的对象,其hashCode必须相等。
假如我们没有覆盖hashCode,则在和集合类对象HashMap、HashSet、和HashTable一起使用时,会出现问题。例子所示:
public class Money {
private BigDecimal ammount;
private String unit;
public Money(BigDecimal ammount, String unit){
this.ammount= ammount;
this.unit = unit;
}
public BigDecimal getAmmount() {
return ammount;
}
public void setAmmount(BigDecimal ammount) {
this.ammount = ammount;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Money)) {
return false;
}
Money m = (Money) o;
return (ammount == null) || ammount.equals(m.getAmmount()) && (unit == null) || unit.equals(m.getUnit());
}
}
在执行如下测试方法时会发现,print的结果为null
public static void main(String[] args) {
Map m = new HashMap();
m.put(new Money(new BigDecimal(10),"CNY"), 1);
System.out.println(m.get(new Money(new BigDecimal(10),"CNY")));
}
这是因为在Map的get方法中,调用了key的hashCode,如下:
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;
}
不覆盖的情况下会直接用object的hashCode,不会产生正确结果。即hash算法把对象放在一个散列桶里,而get方法却从另一个散列桶取值。
如果在Money类里加上如下散列方法:
@Override
public int hashCode() {
int h=17;
h= 31*h+ ammount.hashCode();
h= 31*h+ unit.hashCode();
return h;
}
运行test,则可以得到正确结果:1
至于为什么使用这种hash散列,这里借鉴了经典hash算法的规则,有一点需要强调,能够运用JVM直接完成的算法(移位等)则要使用这些能够提高速度的方法。*31正是运用了新JVM的特性 他可以转换为 (i<<5)-i
分享到:
相关推荐
2. **hashCode方法**:当覆写`equals`时,必须同时覆写`hashCode`,以保持哈希表的正确性。 3. **toString方法**:为每个类提供一个有意义的字符串表示,方便调试和日志记录。 4. **clone方法**:`clone`方法的覆写...
- Item9:当覆盖equals时,必须同时覆盖hashcode,以保持哈希表的行为一致性。 - Item10:toString方法应返回对象状态的简洁表示,便于调试和日志记录。 - Item11:谨慎覆盖clone方法,因为它涉及到对象的深拷贝...
Joshua Bloch 所著《Effective Java 第二版》一书摘要这是我对 Joshua Bloch 所著《Effective Java 第 2 版》的总结。我在学习时会用到它,也可以作为快速参考。它并不是这本书的独立替代品,所以如果你真的想学习...
3. **方法覆盖和重载**:Item 26 "优先考虑使用泛型方法" 提示我们如何通过泛型提高方法的通用性,而Item 27 "避免在重写方法中抛出新异常或不抛出异常" 关注的是多态性的正确实现。 4. **异常处理**:Item 36 "尽...
15. **覆盖equals()时,也应覆盖hashCode()**:这样可以确保对象在哈希表(如HashMap)中的正确行为。 以上只是《Effective Java》第二版部分关键知识点的概述,实际上,书籍中还包含更多关于类设计、方法设计、多...
- 在覆盖`equals`方法的同时覆盖`hashCode`方法。 - 两个根据`equals`方法相等的对象必须具有相同的哈希码。 ##### Item9:始终覆盖`toString` - **目的**:提高调试和日志记录的便利性。 - **实现方式**: - ...
- **项04:始终覆盖hashCode**:当重写了equals方法时,必须同时重写hashCode方法以保持一致性。 - **项05:谨慎覆盖finalize**:finalize方法主要用于执行资源清理工作,但其效率低下且不可预测,应尽量避免使用。 ...
《有效的Java》是Java开发领域的一本经典著作,由Joshua Bloch撰写,它为Java程序员提供了一系列实用的编程准则和最佳实践。本书的核心理念是提高代码质量、可读性和可维护性,通过一系列条目介绍了如何编写更高效、...
8. ** equals() 和 hashCode()**:如果重写了`equals()`方法,一定要同时重写`hashCode()`以保持一致性。 9. **代码风格**:遵循一定的代码风格,例如Google的Java编程风格指南,它规定了如何处理导入、空格、注释...