计算hashCode的常见方法

1. 把某个非零常数值,比如说17,保存在一个叫result的int类型的变量中。

2.对于对象中每一个关键域f(值equals方法中考虑的每一个域),完成以下步骤:

a.为该域计算int类型的散列吗c:

 i. 如果该域是boolean类型,则计算

f?0:1
ii. 如果该域是byte、char、short或者int类型,则计算

(int)f

iii.如果该域是long类型,则计算

(int)(f ^ (f >>> 32))

iv. 如果该域是double类型,则计算

Double.doubleToLongBits(f)

得到一个long类型的值,然后按照2.a.iii,对该long型值计算散列值。

vi. 如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样对这个域递归调用hashCode,如果要求一个更为复杂的比较,则为这个域计算一个“规范表示(canonical representation)”,然后针对这个范式调用hashCode。如果这个域为null,则返回0(或者是某个常数,但习惯上使用0)。

vii. 如果该域是一个数组,则把每一个元素当做单独的域处理。也就是说,递归地应用上诉规则,对每一个重要的元素计算散列值,然后根据2.b的方法把这些散列值组合起来。

b.按照下面的公式,把步骤a得到的散列值组合到result中:

result = 37 * result + c;

3.返回result

4.写完了hashCode后,问自己相等的实例具有相同的hashCode么?假如不是,找出原因并修正。

在散列码的计算过程中,把冗余域排除在计算之外是可以接受的。换句话说,如果一个域的值可以根据其他域值计算出来,则把这样的域排除在外是可以接受的。


举例,假如一个类PhoneNumber有三个关键域:areaCode,exchange,extension,都是short类型,则hashCode的计算过程为:

@Override
public int hashCode(){
    int result = 17;
    result = result * 37 + areaCode;
    result = result * 37 + exchange;
    result = result * 37 + extension;
    return result;
}
如果一个类是可变的,并且计算散列码的代价也比较大,那么你应该考虑把散列码缓存到对象的内部,而不是每次请求的时候都计算散列值。如果你觉得这种类型的大都数值会被用作散列键,那么你应该在实例被创建的时候计算散列值,否则,你可以选择“延迟初始化”散列码,一直到hashCode第一次调用才开始计算。

假如PhoneNumber这样处理,那么代码为:

//延迟初始化
private volatile int hashCode = 0;

@Override
public int hashCode(){
      if(hashCode == 0){
         int result = 17;
         result = result * 37 + areaCode;
         result = result * 37 + exchange;
         result = result * 37 + extension;
         hashCode = result;
      }
      return hashCode;
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 使用哈希算法来生成哈希码,可以使用以下代码:string hashcode = "";using (System.Security.Cryptography.MD5 md5Hash = System.Security.Cryptography.MD5.Create()) { byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); // Create a new Stringbuilder to collect the bytes // and create a string. StringBuilder sBuilder = new StringBuilder(); // Loop through each byte of the hashed data // and format each one as a hexadecimal string. for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } // Return the hexadecimal string. hashcode = sBuilder.ToString(); } ### 回答2: 生成计算hashcode代码的过程主要涉及以下几个步骤: 1. 首先,选择一个合适的哈希算法,例如常用的MD5、SHA-1或者SHA-256等。 2. 定义一个计算哈希值的方法,该方法的返回值类型为int,通常命名为hashCode()。 3. 在该方法中,根据对象的属性或内容计算出哈希码。根据具体的需求可以选择不同的属性参与哈希计算,一般来说需要考虑对象的唯一性和散列性。 4. 在计算哈希码的过程中,可以利用哈希算法提供的功能函数,例如MessageDigest类提供的update()方法,以及digest()方法来获取最终的哈希值。 5. 在计算过程中,需要注意对空值的处理,避免引发空指针异常。 以下是一个示例代码,以字符串为例计算哈希码: public class SampleClass { private String data; public SampleClass(String data) { this.data = data; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((data == null) ? 0 : data.hashCode()); return result; } } 在上述代码中,我们选择了经典的hashcode算法,使用了一些常量和变量来实现哈希码的计算。在计算过程中,首先判断data是否为空,如果为空则返回0,如果不为空则返回data的哈希码乘以一个质数31,最后将结果返回作为该对象的哈希码。 以上就是生成计算哈希码的代码的一个简单示例,可以根据具体的需求和数据类型进行适当的更改和调整。 ### 回答3: 生成计算hashcode代码的关键是要根据对象的特征和属性来确定唯一的哈希值。一般来说,一个良好的哈希函数应具备以下几个特点: 1. 一致性:对于相同的输入值,在程序的多次执行过程中,应始终返回相同的哈希值。 2. 高效性:计算哈希值的时间应尽量短,以提高程序的运行效率。 3. 均匀性:尽可能均匀地将不同的输入映射到哈希值域中。 常见的哈希函数设计方案有以下几种: 1. 基本方案:对于基本数据类型,可以直接使用其内置的哈希函数,例如整数类型直接返回其值,字符串类型使用字符串的哈希函数。 2. 自定义方案:对于自定义的类对象,需要根据对象的属性来计算哈希值。可以选择部分或全部属性来进行哈希计算,要保证选择的属性具有每个对象的唯一性。 3. 组合方案:对于包含多个属性的对象,可以将每个属性的哈希值进行运算(如异或、求和等)来得到最终的哈希值。 4. 拉链法方案:对于哈希冲突较多的情况,可以使用拉链法来解决。即在哈希表中,每个槽位存储一个链表,具有相同哈希值的对象会存储在同一个链表中。 以Java语言为例,生成计算hashcode的代码可以如下所示: ```java @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((property1 == null) ? 0 : property1.hashCode()); result = prime * result + ((property2 == null) ? 0 : property2.hashCode()); // 其他属性的哈希计算 return result; } ``` 这是一个自定义的哈希函数示例,通过将对象的属性哈希值相加得到最终的哈希值。其中,prime是一个质数,用于增加哈希值的随机性。对于每个属性,如果属性为null,则返回0;否则,返回属性的哈希值。 通过实现良好的哈希函数,可以保证哈希表等数据结构在存储和查找对象时具有良好的性能和均匀性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值