热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Eclipse生成的hashCode函数是否有用?-IsthehashCodefunctiongeneratedbyEclipseanygood?

EclipsesourcemenuhasageneratehashCodeequalsmethodwhichgeneratesfunctionsliketheone

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

Eclipse源菜单有一个“生成hashCode / equals方法”,它生成如下所示的函数。

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.

如果我在生成hashCode()和equals()时选择多个字段,则Eclipse使用上面显示的相同模式。

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?

我不是哈希函数的专家,我想知道生成的哈希函数是多么“好”?在什么情况下它会崩溃并导致太多碰撞?

8 个解决方案

#1


16  

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

您可以在java.util.ArrayList中看到hashCode函数的实现

public int hashCode() {
    int hashCode = 1;
    Iterator 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,

这是一个这样的例子,您的Eclipse生成的代码遵循类似的实现方式。但是如果你觉得你必须自己实现你的hashCode,那么Joshua Bloch在他的着名书籍Effective Java中给出了一些很好的指导。我将从该书的第9项中发布那些重要的观点。那些是,

  1. Store some constant nonzero value, say, 17, in an int variable called result.
  2. 在一个名为result的int变量中存储一些常量非零值,比如17。

  3. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:

    对于对象中的每个重要字段f(通过equals方法考虑的每个字段,即),执行以下操作:

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

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

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

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

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

    II。如果字段是byte,char,short或int,则为compute(int)f。

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

    III。如果字段是long,则计算(int)(f ^(f >>> 32))。

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

    IV。如果该字段是浮点数,则计算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.

    v。如果该字段是double,则计算Double.doubleToLongBits(f),然后在步骤2.a.iii中对生成的long进行哈希处理。

    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)

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

    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.

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

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

    湾将步骤2.a中计算的哈希码c组合到结果中,如下所示:

       result = 31 * result + c;
    
  4. Return result.

  5. 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.

    编写完hashCode方法后,请问自己,相等的实例是否具有相同的哈希码。编写单元测试来验证你的直觉!如果相等的实例具有不相等的哈希码,请弄清楚原因并解决问题。

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

我认为Java语言设计者和Eclipse似乎遵循类似的指导原则。快乐的编码。干杯。

#2


10  

Since Java 7 you can use java.util.Objects to write short and elegant methods:

从Java 7开始,您可以使用java.util.Objects编写简短而优雅的方法:

class Foo {
  private String name;
  private String id;

  @Override
  public int hashCode() {
    return Objects.hash(name,id);
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Foo) {
      Foo right = (Foo) obj;
      return Objects.equals(name,right.name) && Objects.equals(id,right.id);
    }
    return false;
  }
}

#3


5  

Generally it is good, but:

一般来说它很好,但是:

  1. Guava does it somehow better, I prefer it. [EDIT: It seems that as of JDK7 Java provides a similar hash function].
  2. 番石榴做得更好,我更喜欢它。 [编辑:似乎从JDK7开始Java提供了类似的哈希函数]。

  3. Some frameworks can cause problems when accessing fields directly instead of using setters/getters, like Hibernate for example. For some fields that Hibernate creates lazy, it creates a proxy not the real object. Only calling the getter will make Hibernate go for the real value in the database.
  4. 一些框架在直接访问字段时可能会导致问题,而不是像使用Hibernate那样使用setter / getter。对于Hibernate创建惰性的一些字段,它创建代理而不是真实对象。只有调用getter才能使Hibernate在数据库中获得真正的价值。

#4


4  

Yes, it is perfect :) You will see this approach almost everywhere in the Java source code.

是的,它是完美的:)您将在Java源代码中几乎无处不在地看到这种方法。

#5


0  

It's a standard way of writing hash functions. However, you can improve/simplify it if you have some knowledge about the fields. E.g. you can ommit the null check, if your class guarantees that the field never be null (applies to equals() as well). Or you can of delegate the field's hash code if only one field is used.

这是编写哈希函数的标准方法。但是,如果您对字段有一些了解,则可以改进/简化它。例如。如果你的类保证字段永远不为null(也适用于equals()),你可以省略null检查。或者,如果只使用一个字段,则可以委派字段的哈希码。

#6


0  

I would also like to add a reference to Item 9, in Effective Java 2nd Edition by Joshua Bloch.

我还想在Joshua Bloch的Effective Java 2nd Edition中添加对Item 9的引用。

Here is a recipe from Item 9 : ALWAYS OVERRIDE HASHCODE WHEN YOU OVERRIDE EQUALS

这是第9项的配方:当你超越平等时总是覆盖哈希码

  1. Store some constant nonzero value, say, 17, in an int variable called result.
  2. 在一个名为result的int变量中存储一些常量非零值,比如17。

  3. For each significant field f in your object (each field taken into account by the equals method, that is), do the following:
  4. 对于对象中的每个重要字段f(通过equals方法考虑的每个字段,即),执行以下操作:

    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.

#7


0  

If you are using Apache Software Foundation (commons-lang library) then below classes will help you to generate hashcode/equals/toString methods using reflection.

如果您使用的是Apache Software Foundation(commons-lang库),那么下面的类将帮助您使用反射生成hashcode / equals / toString方法。

You don't need to worry about regenerating hashcode/equals/toString methods when you add/remove instance variables.

添加/删除实例变量时,无需担心重新生成hashcode / equals / toString方法。

EqualsBuilder - This class provides methods to build a good equals method for any class. It follows rules laid out in Effective Java , by Joshua Bloch. In particular the rule for comparing doubles, floats, and arrays can be tricky. Also, making sure that equals() and hashCode() are consistent can be difficult.

EqualsBuilder - 这个类提供了为任何类构建一个好的equals方法的方法。它遵循Joshua Bloch撰写的Effective Java中规定的规则。特别是比较双精度数,浮点数和数组的规则可能很棘手。此外,确保equals()和hashCode()一致可能很困难。

HashCodeBuilder - This class enables a good hashCode method to be built for any class. It follows the rules laid out in the book Effective Java by Joshua Bloch. Writing a good hashCode method is actually quite difficult. This class aims to simplify the process.

HashCodeBuilder - 这个类可以为任何类构建一个好的hashCode方法。它遵循Joshua Bloch撰写的Effective Java一书中规定的规则。编写一个好的hashCode方法实际上非常困难。本课程旨在简化流程。

ReflectionToStringBuilder - This class uses reflection to determine the fields to append. Because these fields are usually private, the class uses AccessibleObject.setAccessible(java.lang.reflect.AccessibleObject[], boolean) to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are set up correctly.

ReflectionToStringBuilder - 此类使用反射来确定要追加的字段。因为这些字段通常是私有的,所以该类使用AccessibleObject.setAccessible(java.lang.reflect.AccessibleObject [],boolean)来更改字段的可见性。除非正确设置了适当的权限,否则这将在安全管理器下失败。

Maven Dependency:


        commons-lang
        commons-lang
        ${commons.lang.version}

Sample Code:

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

public class Test{

    instance variables...
    ....

    getter/setter methods...
    ....

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }
}

#8


0  

One potential drawback is that all objects with null fields will have a hash code of 31, thus there could be many potential collisions between objects that only contain null fields. This would make for slower lookups in Maps.

一个潜在的缺点是具有空字段的所有对象将具有31的散列码,因此在仅包含空字段的对象之间可能存在许多潜在的冲突。这会使地图中的查找速度变慢。

This can occur when you have a Map whose key type has multiple subclasses. For example, if you had a HashMap


推荐阅读
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
author-avatar
jelly62_736
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有