为基于值的 类 预计算 hashCode?
Precompute hashCode for value-based classes?
基于值的 classes 具有 属性 他们
are final and immutable (though may contain references to mutable objects).
因此,如果您知道您的对象仅包含不可变实例,则可以预先计算该实例的 hashCode
。这可以在使用 Map
或 Set
操作时加快访问速度。
看看 Instant
中 hashCode
的实现,这是一个基于值的 class,为什么开发人员决定反对这种模式?预先计算 hashCode
的性能损失是否会比在需要时一遍又一遍地计算更重要?
// copied from Instant#hashCode
@Override
public int hashCode() {
return ((int) (seconds ^ (seconds >>> 32))) + 51 * nanos;
}
那么,在什么条件下预计算 hashCode
合理?
Instant
不缓存 hashcode
并没有直接的原因。但是我能想到的一些:
缓存hashcode
是有代价的:声明的实例变量:
- 它当然会占用每个对象更多的内存。重新计算哈希码可能没问题,而不是为每个实例对象分配额外的内存
- 担心 serialization/deserialization,因为需要保留实例变量。增加序列化对象的大小
- 内部实现在以后的版本中很难修改。尤其是因为过去的序列化对象。对于过去的版本对象,保持向后兼容性变得困难。额外维护。
hashcode
可能永远不会在 Instant 对象上调用。在这种情况下,我们浪费 CPU 来计算从未使用过的东西
所以缓存可能没有意义。可能对 String
有意义,因为它在整个过程中都很常用。可能值得头疼。
基于值的 classes 具有 属性 他们
are final and immutable (though may contain references to mutable objects).
因此,如果您知道您的对象仅包含不可变实例,则可以预先计算该实例的 hashCode
。这可以在使用 Map
或 Set
操作时加快访问速度。
看看 Instant
中 hashCode
的实现,这是一个基于值的 class,为什么开发人员决定反对这种模式?预先计算 hashCode
的性能损失是否会比在需要时一遍又一遍地计算更重要?
// copied from Instant#hashCode
@Override
public int hashCode() {
return ((int) (seconds ^ (seconds >>> 32))) + 51 * nanos;
}
那么,在什么条件下预计算 hashCode
合理?
Instant
不缓存 hashcode
并没有直接的原因。但是我能想到的一些:
缓存hashcode
是有代价的:声明的实例变量:
- 它当然会占用每个对象更多的内存。重新计算哈希码可能没问题,而不是为每个实例对象分配额外的内存
- 担心 serialization/deserialization,因为需要保留实例变量。增加序列化对象的大小
- 内部实现在以后的版本中很难修改。尤其是因为过去的序列化对象。对于过去的版本对象,保持向后兼容性变得困难。额外维护。
hashcode
可能永远不会在 Instant 对象上调用。在这种情况下,我们浪费 CPU 来计算从未使用过的东西
所以缓存可能没有意义。可能对 String
有意义,因为它在整个过程中都很常用。可能值得头疼。