是否由Eclipse生成的hashCode函数好吗? [英] Is the hashCode function generated by Eclipse any good?

查看:261
本文介绍了是否由Eclipse生成的hashCode函数好吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Eclipse源菜单有一个生成hashCode / equals方法,它生成下面的函数。

 字符串名称; 
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result +((name == null)?0:name.hashCode());
返回结果;
}

@Override
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass()!= obj.getClass())
return false;
CompanyRole other =(CompanyRole)obj;
if(name == null)
{
if(other.name!= null)
return false;
} else if(!name.equals(other.name))
return false;
返回true;
}

如果在生成 hashCode()时选择多个字段, equals() Eclipse使用与上述相同的模式。



我不是哈希函数的专家,我想知道生成的哈希函数的好是什么?什么情况会分解,造成太多的碰撞?

解决方案

您可以在 java.util.ArrayList as

  public int hashCode(){
int hashCode = 1;
迭代器< E> i = iterator();
while(i.hasNext()){
E obj = i.next();
hashCode = 31 * hashCode +(obj == null?0:obj.hashCode());
}
返回hashCode;
}

这是一个这样的例子,Eclipse生成的代码遵循类似的实现方式它。但是如果你觉得你必须自己实现你的hashCode,Joshua Bloch在他着名的书籍中提供了一些很好的指南有效Java 。我会把这本书的第9项重要内容发表。这些是



  1. 在一个名为result的int变量中存储一些常量的非零值,例如17。 / li>
  2. 对于对象中的每个重要字段f(通过equals方法考虑每个字段),请执行以下操作:



    a。为字段计算一个int哈希码c:



    i。如果该字段是一个布尔值,则计算(f?1:0)。



    ii。如果字段是字节,char,short或int,则compute(int)f。



    iii。如果字段长,compute(int)(f ^(f >>> 32))。



    iv。如果该字段是浮点数,则计算Float.floatToIntBits(f)。



    v。如果字段是双精度,则计算Double.doubleToLongBits(f),然后像步骤2.a.iii中那样哈希生成的long。



    vi。如果该字段是一个对象引用,并且该类的equals方法通过递归调用equals比较该字段,则递归地调用该字段上的hashCode。如果需要更复杂的比较,请计算此字段的规范表示,并在规范表示上调用hashCode。如果该字段的值为空,则返回0(或其他一些常量,但是0是传统的)



    vii。如果该字段是数组,则将其视为每个元素都是单独的字段。
    即,通过递归地应用
    计算每个有效元素的哈希码,并且每个步骤2.b组合这些值。如果数组字段中的每个
    元素都很重要,可以使用1.5版本中添加的
    Arrays.hashCode方法之一。



    b。将步骤2.a中计算的哈希代码c合并成如下结果:

      result = 31 * result + c; 


  3. 返回结果


  4. 完成hashCode方法的编写后,请问自己是否
    相等的实例具有相等的哈希码。编写单元测试来验证你的直觉!
    如果相等的实例具有不等的哈希码,可以找出为什么并解决问题。



Java语言设计人员和Eclipse似乎遵循类似的指导方针。快乐编码。干杯。


Eclipse source menu has a "generate hashCode / equals method" which generates functions like the one below.

String name; 
@Override
public int hashCode()
{
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}

@Override
public boolean equals(Object obj)
{
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    CompanyRole other = (CompanyRole) obj;
    if (name == null)
    {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
}

If I select multiple fields when generating hashCode() and equals() Eclipse uses the same pattern shown above.

I am not an expert on hash functions and I would like to know how "good" the generated hash function is? What are situations where it will break down and cause too many collisions?

解决方案

You can see the implementation of hashCode function in java.util.ArrayList as

public int hashCode() {
    int hashCode = 1;
    Iterator<E> i = iterator();
    while (i.hasNext()) {
        E obj = i.next();
        hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
    }
    return hashCode;
}

It is one such example and your Eclipse generated code follows a similar way of implementing it. But if you feel that you have to implement your hashCode by your own, there are some good guidelines given by Joshua Bloch in his famous book Effective Java. I will post those important points from Item 9 of that book. Those are,

  1. Store some constant nonzero value, say, 17, in an int variable called result.
  2. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:

    a. Compute an int hash code c for the field:

    i. If the field is a boolean, compute (f ? 1 : 0).

    ii. If the field is a byte, char, short, or int, compute (int) f.

    iii. If the field is a long, compute (int) (f ^ (f >>> 32)).

    iv. If the field is a float, compute Float.floatToIntBits(f).

    v. If the field is a double, compute Double.doubleToLongBits(f), and then hash the resulting long as in step 2.a.iii.

    vi. If the field is an object reference and this class’s equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If a more complex comparison is required, compute a "canonical representation" for this field and invoke hashCode on the canonical representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional)

    vii. If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine these values per step 2.b. If every element in an array field is significant, you can use one of the Arrays.hashCode methods added in release 1.5.

    b. Combine the hash code c computed in step 2.a into result as follows:

       result = 31 * result + c;
    

  3. Return result.

  4. When you are finished writing the hashCode method, ask yourself whether equal instances have equal hash codes. Write unit tests to verify your intuition! If equal instances have unequal hash codes, figure out why and fix the problem.

Java language designers and Eclipse seem to follow similar guidelines I suppose. Happy coding. Cheers.

这篇关于是否由Eclipse生成的hashCode函数好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆