ii. 如果域是一个 byte , char , short , int ,计算 c=(int)f
iii.如果域是一个 long 类型,计算 c=(int)(f^(f>>>32)).
iv.如果域是一个 float 类型,计算 c=Float.floatToIntBits(f).
v.如果域是一个 double 类型,计算 long l = Double.doubleToLongBits(f) , c = (int)(l^(l>>>32))
vi.如果该字段是对象引用,则 equals() 为该字段调用 equals()。计算 c = f.hashCode()
vii.如果域是一个数组,将其视为每个元素都是一个单独的字段 。
也就是说,通过将上述规则应用于每个元素来为每个重要元素计算 hashCode 。
b.将步骤2.a中计算的 hashCode c 组合到结果中,如下所示:result = 37 * result + c;
- 返回结果值
- 查看生成的 hashCode() 并确保相等的实例具有相同的哈希码 。
以下是遵循上述准则的类的示例
public class HashTest {private String field1;private short field2;@Overridepublic int hashCode() {int result = 17;result = 37*result + field1.hashCode();result = 37*result + (int)field2;return result;}}您可以看到选择常数37 。选择这个数字的目的是它是一个素数 。我们可以选择任何其他素数 。
1.3.3 Apache HashCodeBuilder
编写好的 hashCode() 方法并不总是那么容易 。由于正确实现 hashCode() 可能很困难,如果我们有一些可重用的实现,将会很有帮助 。Jakarta-Commonsorg.apache.commons.lang.builder 包提供了一个名为 HashCodeBuilder 的类,旨在帮助实现 hashCode()方法 。通常,开发人员很难实现 hashCode() 方法,这个类旨在简化流程 。
以下是为上述类实现 hashCode 算法的方法:
public class HashTest {private String field1;private short field2;@Overridepublic int hashCode() {return new HashCodeBuilder(83, 7) .Append(field1) .append(field2) .toHashCode();} }请注意,构造函数的两个数字只是两个不同的非零奇数 - 这些数字有助于避免跨对象的 hashCode 值的冲突 。
如果需要,可以使用 appendSuper(int) 添加超类 hashCode()。
您可以看到使用 Apache HashCodeBuilder 重写 HashCode() 是多么容易 。
1.4 可变对象作为 key
一般建议您应该使用不可变对象作为 Collection 中的键 。从不可变数据计算时, HashCode 效果最佳 。如果您使用可变对象作为键并更改对象的状态以便hashCode更改,那么存储对象将位于 Collection 中的错误存储桶中 。在实现 hashCode() 时,您应该考虑的最重要的事情是,无论何时调用此方法,它都应该在每次调用时为特定对象生成相同的值 。如果你有一个类似于一个对象的场景,当它被 put() 到一个HaspMap并在 get() 期间产生另一个值时会产生一个 hashCode()值, 在这种情况下,你将无法检索该对象 。
因此,如果您的 hashCode() 依赖于对象中的可变数据,那么通过生成不同的 hashCode(),更改这些数据肯定会产生不同的密钥 。
看下面的例子:
public class Employee {private String name;private int age;public Employee() { }public Employee(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;} public void setName(String name) { this.name = name; }public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object obj) {//Remember: Some Java gurus recommend you avoid using instanceofif (obj instanceof Employee) {Employee emp = (Employee)obj;return (emp.name == name && emp.age == age);}return false;}@Overridepublic int hashCode() {return name.length() + age;}public static void main(String[] args) {Employee e = new Employee("muhammad", 24);Map<Object, Object> m = new HashMap<Object, Object>();m.put(e, "Muhammad Ali Khojaye");// getting output System.out.println(m.get(e)); e.name = "abid";// it fails to get System.out.println(m.get(e)); e.name = "amirrana";// it fails again System.out.println(m.get(new Employee("muhammad", 24))); } }因此,您可以在上面的示例中看到我们如何获得一些不可预测的结果 。您可以使用 Joshua Recipe 或使用 HashCodeBuilder 类重写 hashCode() 来轻松修复上述问题 。
这是一个例子:
1.4.1 示例建议:
@Override public int hashCode() { int result = 17;result = 37*result + name.hashCode();result = 37*result + age;return result; }1.4.2 使用HashCodeBuilder
@Overridepublic int hashCode() {return new HashCodeBuilder(83, 7).append(name).append(age).toHashCode(); }1.4.3 可变字段作为键的另外一个例子
让我们来看一下这个例子:
public class HashTest { private int mutableField; private final int immutableField;public HashTest(int mutableField, int immutableField) {this.mutableField = mutableField;this.immutableField = immutableField;}public void setMutableField(int mutableField) {this.mutableField = mutableField;}@Overridepublic boolean equals(Object o) {if(o instanceof HashTest) {return (mutableField == ((HashTest)o).mutableField) && (immutableField == ((HashTest)o).immutableField);}else {return false;}} @Overridepublic int hashCode() {int result = 17; result = 37 * result + this.mutableField;result = 37 * result + this.immutableField;return result;}public static void main(String[] args) {Set<HashTest> set = new HashSet<HashTest>();HashTest obj = new HashTest(6622458, 626304);set.add(obj); System.out.println(set.contains(obj));obj.setMutableField(3867602);System.out.println(set.contains(obj));}}
推荐阅读
-
胡须发白发红,头发也变白了,是缺少哪些微量元素吃善存是不是有效果
-
-
梅西|重磅!外媒确认梅西已告知巴萨将离队,网友道别:再见一代天王
-
『技术』“云上”生产 “网上”销售 “线上”生活——数字技术激发乡村经济新潜能
-
文化历史太有趣:伊拉克战争却选择了放弃抵抗,萨达姆最信任的两支嫡系部队
-
新华网|各部门助力“双11”电商黄金周货品“快速达”
-
新车|这辆“M”不太凶!宝马i4 M谍照曝光,明年正式亮相
-
辉说体育|这些球员终于在今天实现了NBA夺冠梦想,等待多年
-
电影|今年是恐怖电影的大年,部部爆红,你看过哪几部?
-
黄磊|限薪令下的阳奉阴违,黄磊天价片酬曝光,四部戏狂赚1.5亿!
-
[肖战]肖战发布全新单曲《光点》:不要捧杀我,我只想做自己
-
健康|有脂肪肝怎么办?提醒:这3条妙计,把肝脏的脂肪“减”下去
-
喵家影视|快来做一个吧,变废为宝好简单!分享几十款旧衣服制作的包包
-
南阳情感帮|见前男友最后一面,只为了断往事,能不能信,准新娘结婚前3天
-
门锁|百万爆款门锁升级版来了!小米智能门锁1S上架:999元
-
穿搭|越矛盾越时髦,现在就是穿短袖针织的最好季节呀
-
-
艾滋病病毒|要爱,不要艾!关于艾滋病的这些知识你需要了解
-
-