编辑:准备我的对象以在 HashMap 中使用。
在阅读了一些有关如何生成哈希码的信息后,我现在有点困惑。我的(可能是微不足道的)问题是,当我有一个可以使用的字段时,我应该如何实现 hashCode 方法?我可以直接使用字段吗?
如果我理解正确,则 hashCode 的值在对象的生命周期内不得更改,并且我只有一个适合此的 ID 归档,但我在其他地方读过,不应该使用 ID...尽管如此,如何基于这个(唯一且不变)值的 hashCode 函数会是什么样子? equals方法也是仅基于id..
Edit: Prepare my objects for the use within a HashMap.
after reading a bit about how to generate a hash code, im kind of confused now. My (probably trivial) question is, how should I implement a hashCode method when I have one field that I could use? Can I use the fiels directly?
If I understand correctly, the values for hashCode must not change during the lifetime of an object, and I only have an ID filed that fits this, but I have read otherwhere, that one should not use ID...despide of that, how would a hashCode function based on this one (unique and not changing) value look like? The equals method is also based on the id only..
发布评论
评论(3)
如果您的对象是可变的,那么其哈希码随时间变化是可以接受的。当然,您应该更喜欢不可变对象(Effective Java 第 2 版,第 15 项:最小化可变性)。
以下是 Josh Bloch 的哈希码配方,来自 Effective Java 第 2 版,第 9 项:当您覆盖
equals
时,始终覆盖hashCode
:Effective Java 第 2 版哈希码配方
result
的int
变量中。int
哈希码c
:布尔值
,则计算(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
。如果该字段的值为null
,则返回0。c
组合成result
,如下所示:result = 31 * result + c;
按原样遵循配方是正确的,即使只有一个字段。只需根据字段的类型执行适当的操作即可。
请注意,有些库实际上可以为您简化此操作,例如 Apache Commons Lang 的“noreferrer">
HashCodeBuilder
,或者只是来自 >java.util.Arrays
。这些库允许您简单地编写如下内容:
Apache Commons Lang 示例
这是使用 Apache Commons Lang 的构建器来促进方便且可读的
equals
、hashCode
、toString
和compareTo
:这四种方法编写起来非常繁琐,并且很难确保遵守所有约定,但幸运的是库至少可以帮助让工作变得更容易。一些 IDE(例如 Eclipse)还可以自动为您生成其中一些方法。
另请参阅
EqualsBuilder
HashCodeBuilder
ToStringBuilder
CompareToBuilder
equals
时遵守通用合同equals
时始终覆盖hashCode
toString
Comparable
If your object is mutable, then it is acceptable to have its hash code change over time. Of course, you should prefer immutable objects (Effective Java 2nd Edition, Item 15: Minimize mutability).
Here's the hashcode recipe from Josh Bloch, from Effective Java 2nd Edition, Item 9: Always override
hashCode
when you overrideequals
:Effective Java 2nd Edition hash code recipe
int
variable calledresult
.int
hashcodec
for each field:boolean
, compute(f ? 1 : 0)
byte, char, short, int
, compute(int) f
long
, compute(int) (f ^ (f >>> 32))
float
, computeFloat.floatToIntBits(f)
double
, computeDouble.doubleToLongBits(f)
, then hash the resultinglong
as in above.equals
method compares the field by recursively invokingequals
, recursively invokehashCode
on the field. If the value of the field isnull
, return 0.Arrays.hashCode
methods added in release 1.5.c
intoresult
as follows:result = 31 * result + c;
It would be correct to follow the recipe as is, even with just one field. Just do the appropriate action depending on the type of the field.
Note that there are libraries that actually simplify this for you, e.g.
HashCodeBuilder
from Apache Commons Lang, or justArrays.hashCode/deepHashCode
fromjava.util.Arrays
.These libraries allows you to simply write something like this:
Apache Commons Lang example
Here's a more complete example of using the builders from Apache Commons Lang to facilitate a convenient and readable
equals
,hashCode
,toString
, andcompareTo
:These four methods can be notoriously tedious to write, and it can be difficult to ensure that all of the contracts are adhered to, but fortunately libraries can at least help make the job easier. Some IDEs (e.g. Eclipse) can also automatically generate some of these methods for you.
See also
EqualsBuilder
HashCodeBuilder
ToStringBuilder
CompareToBuilder
equals
hashCode
when you overrideequals
toString
Comparable
如果您希望具有不同 id 的对象由该 id 标识,您需要做的就是返回它/比较它。
If you want objects with different ids to identified by that id all you need to do is return it/compare it.
用多少个字段来计算hashCode并不重要。
但使用equals()很重要。如果A等于B,则它们的hashCode必须相同。
如果你讨厌 hashCode:) 并且你的对象永远不会被放入基于哈希的容器(HashMap、HashSet ..),只需保留 hashCode() ,让其基类计算 hashCode 即可。
It does not matter that how many fields are used to calculate hashCode.
But it matters working with equals(). If A equals B, their hashCode must be same.
If you hate hashCode:) and your object never be put to hash based containers(HashMap, HashSet..), just leave hashCode() alone, let its base class to calculate hashCode.