编辑:准备我的对象以便在HashMap中使用。
在阅读了一些关于如何生成哈希码的内容之后,我现在很困惑。我的(可能是微不足道的)问题是,当我有一个可以使用的字段时,我应该如何实现hashCode方法?我可以直接使用fiels吗? 如果我理解正确的话,hashCode的值在对象的生命周期内不能改变,我只有一个适合这个的ID,但是我已经在其他地方读过,那个人不应该使用ID ...这个怎么样,怎么样一个基于这个(唯一且没有变化)值的hashCode函数会是什么样的? equals方法也仅基于id ..答案 0 :(得分:15)
如果您的对象是可变的,则可以随时更改其哈希代码。当然,您应该更喜欢不可变对象( Effective Java 2nd Edition,Item 15:Minimize mutability )。
以下是来自 Effective Java 2nd Edition的Josh Bloch的哈希码配方,第9项:覆盖hashCode
时始终覆盖equals
:
int
的{{1}}变量中。result
哈希码int
:
c
,请计算boolean
(f ? 1 : 0)
,请计算byte, char, short, int
(int) f
,请计算long
(int) (f ^ (f >>> 32))
,请计算float
Float.floatToIntBits(f)
,请计算double
,然后对结果Double.doubleToLongBits(f)
进行哈希处理,如上所述。long
方法通过递归调用equals
来比较字段,则在该字段上递归调用equals
。如果字段的值为hashCode
,则返回0. null
方法之一。Arrays.hashCode
合并到c
中,如下所示:result
按照原样配方是正确的,即使只有一个字段。只需根据字段的类型执行相应的操作。
请注意,有些库实际上可以为您简化此操作,例如:来自HashCodeBuilder
的Apache Commons Lang,或来自java.util.Arrays
的result = 31 * result + c;
。
这些库允许您简单地编写如下内容:
Arrays.hashCode/deepHashCode
这是一个更完整的示例,使用Apache Commons Lang中的构建器来方便可读@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
field1, field2, field3, //...
});
}
,equals
,hashCode
和toString
:
compareTo
这四种方法的编写非常繁琐,而且很难确保所有合同都得到遵守,但幸运的是,图书馆至少可以帮助您轻松完成工作。某些IDE(例如Eclipse)也可以自动为您生成其中一些方法。
import org.apache.commons.lang.builder.*;
public class CustomType implements Comparable<CustomType> {
// constructors, etc
// let's say that the "significant" fields are field1, field2, field3
@Override public String toString() {
return new ToStringBuilder(this)
.append("field1", field1)
.append("field2", field2)
.append("field3", field3)
.toString();
}
@Override public boolean equals(Object o) {
if (o == this) { return true; }
if (!(o instanceof CustomType)) { return false; }
CustomType other = (CustomType) o;
return new EqualsBuilder()
.append(this.field1, other.field1)
.append(this.field2, other.field2)
.append(this.field3, other.field3)
.isEquals();
}
@Override public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(field1)
.append(field2)
.append(field3)
.toHashCode();
}
@Override public int compareTo(CustomType other) {
return new CompareToBuilder()
.append(this.field1, other.field1)
.append(this.field2, other.field2)
.append(this.field3, other.field3)
.toComparison();
}
}
equals
hashCode
equals
toString
答案 1 :(得分:2)
如果您想要通过该ID识别具有不同ID的对象,您需要做的就是返回/比较它。
private final int id;
public int hashCode() { return id; }
public boolean equals(Object o) {
return o instanceof ThisClass && id == ((ThisClass)o).id;
}
答案 2 :(得分:1)
使用多少字段来计算hashCode并不重要。 但是使用 equals()很重要。如果A等于B,则它们的hashCode必须相同。
如果您讨厌hashCode :)并且您的对象永远不会被放到基于散列的容器(HashMap,HashSet ..),只需单独留下hashCode(),让它的基类来计算hashCode。