`
qqdwll
  • 浏览: 136673 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java 实现 hashCode 方法

    博客分类:
  • Java
阅读更多
原文 http://www.javapractices.com/topic/TopicAction.do;jsessionid=8D0BB2D9061334756DC17A10A4FB5F71?Id=28

Implementing hashCode :

    * if a class overrides equals, it must override hashCode
    * when they are both overridden, equals and hashCode must use the same set of fields
    * if two objects are equal, then their hashCode values must be equal as well
    * if the object is immutable, then hashCode is a candidate for caching and lazy initialization

It is a popular misconception that hashCode provides a unique identifier for an object. It does not.

Example

The following utility class allows simple construction of an effective hashCode method. It is based on the recommendations of Effective Java, by Joshua Bloch.

import java.lang.reflect.Array;

/**
* Collected methods which allow easy implementation of <code>hashCode</code>.
*
* Example use case:
* <pre>
*  public int hashCode(){
*    int result = HashCodeUtil.SEED;
*    //collect the contributions of various fields
*    result = HashCodeUtil.hash(result, fPrimitive);
*    result = HashCodeUtil.hash(result, fObject);
*    result = HashCodeUtil.hash(result, fArray);
*    return result;
*  }
* </pre>
*/
public final class HashCodeUtil {

  /**
  * An initial value for a <code>hashCode</code>, to which is added contributions
  * from fields. Using a non-zero value decreases collisons of <code>hashCode</code>
  * values.
  */
  public static final int SEED = 23;

  /**
  * booleans.
  */
  public static int hash( int aSeed, boolean aBoolean ) {
    System.out.println("boolean...");
    return firstTerm( aSeed ) + ( aBoolean ? 1 : 0 );
  }

  /**
  * chars.
  */
  public static int hash( int aSeed, char aChar ) {
    System.out.println("char...");
    return firstTerm( aSeed ) + (int)aChar;
  }

  /**
  * ints.
  */
  public static int hash( int aSeed , int aInt ) {
    /*
    * Implementation Note
    * Note that byte and short are handled by this method, through
    * implicit conversion.
    */
    System.out.println("int...");
    return firstTerm( aSeed ) + aInt;
  }

  /**
  * longs.
  */
  public static int hash( int aSeed , long aLong ) {
    System.out.println("long...");
    return firstTerm(aSeed)  + (int)( aLong ^ (aLong >>> 32) );
  }

  /**
  * floats.
  */
  public static int hash( int aSeed , float aFloat ) {
    return hash( aSeed, Float.floatToIntBits(aFloat) );
  }

  /**
  * doubles.
  */
  public static int hash( int aSeed , double aDouble ) {
    return hash( aSeed, Double.doubleToLongBits(aDouble) );
  }

  /**
  * <code>aObject</code> is a possibly-null object field, and possibly an array.
  *
  * If <code>aObject</code> is an array, then each element may be a primitive
  * or a possibly-null object.
  */
  public static int hash( int aSeed , Object aObject ) {
    int result = aSeed;
    if ( aObject == null) {
      result = hash(result, 0);
    }
    else if ( ! isArray(aObject) ) {
      result = hash(result, aObject.hashCode());
    }
    else {
      int length = Array.getLength(aObject);
      for ( int idx = 0; idx < length; ++idx ) {
        Object item = Array.get(aObject, idx);
        //recursive call!
        result = hash(result, item);
      }
    }
    return result;
  }


  /// PRIVATE ///
  private static final int fODD_PRIME_NUMBER = 37;

  private static int firstTerm( int aSeed ){
    return fODD_PRIME_NUMBER * aSeed;
  }

  private static boolean isArray(Object aObject){
    return aObject.getClass().isArray();
  }
} 


Here is an example of its use. When debugging statements are uncommented in HashCodeUtil, the reuse of the boolean, char, int and long versions of hash is demonstrated :


boolean...
char...
int...
long...
long...
int...
int...
int...
int...
int...
hashCode value: -608077094

import java.util.*;

public final class ApartmentBuilding {

  public ApartmentBuilding (
    boolean aIsDecrepit,
    char aRating,
    int aNumApartments,
    long aNumTenants,
    double aPowerUsage,
    float aWaterUsage,
    byte aNumFloors,
    String aName,
    List aOptions,
    Date[] aMaintenanceChecks
  ){
    fIsDecrepit = aIsDecrepit;
    fRating = aRating;
    fNumApartments = aNumApartments;
    fNumTenants = aNumTenants;
    fPowerUsage = aPowerUsage;
    fWaterUsage = aWaterUsage;
    fNumFloors = aNumFloors;
    fName = aName;
    fOptions = aOptions;
    fMaintenanceChecks = aMaintenanceChecks;
  }

  @Override public boolean equals(Object that) {
    if ( this == that ) return true;
    if ( !(that instanceof ApartmentBuilding) ) return false;
    ApartmentBuilding thatBuilding = (ApartmentBuilding)that;
    return hasEqualState(thatBuilding);
  }

  @Override public int hashCode() {
    //this style of lazy initialization is 
    //suitable only if the object is immutable
    if ( fHashCode == 0) {
      int result = HashCodeUtil.SEED;
      result = HashCodeUtil.hash( result, fIsDecrepit );
      result = HashCodeUtil.hash( result, fRating );
      result = HashCodeUtil.hash( result, fNumApartments );
      result = HashCodeUtil.hash( result, fNumTenants );
      result = HashCodeUtil.hash( result, fPowerUsage );
      result = HashCodeUtil.hash( result, fWaterUsage );
      result = HashCodeUtil.hash( result, fNumFloors );
      result = HashCodeUtil.hash( result, fName );
      result = HashCodeUtil.hash( result, fOptions );
      result = HashCodeUtil.hash( result, fMaintenanceChecks );
      fHashCode = result;
    }
    return fHashCode;
  }

  //..other methods elided

  // PRIVATE ////

  /**
  * The following fields are chosen to exercise most of the different
  * cases.
  */
  private boolean fIsDecrepit;
  private char fRating;
  private int fNumApartments;
  private long fNumTenants;
  private double fPowerUsage;
  private float fWaterUsage;
  private byte fNumFloors;
  private String fName; //possibly null, say
  private List fOptions; //never null
  private Date[] fMaintenanceChecks; //never null
  private int fHashCode;

  /**
  * Here, for two ApartmentBuildings to be equal, all fields must be equal.
  */
  private boolean hasEqualState( ApartmentBuilding that ) {
    //note the different treatment for possibly-null fields
    return
      ( this.fName==null ? that.fName==null : this.fName.equals(that.fName) ) &&
      ( this.fIsDecrepit == that.fIsDecrepit )&&
      ( this.fRating == that.fRating )&&
      ( this.fNumApartments == that.fNumApartments ) &&
      ( this.fNumTenants == that.fNumTenants ) &&
      ( this.fPowerUsage == that.fPowerUsage ) &&
      ( this.fWaterUsage ==  that.fWaterUsage ) &&
      ( this.fNumFloors == that.fNumFloors ) &&
      ( this.fOptions.equals(that.fOptions) )&&
      ( Arrays.equals(this.fMaintenanceChecks, that.fMaintenanceChecks) );
  }

  /**
  * Exercise hashcode.
  */
  public static void main (String [] aArguments) {
    List options = new ArrayList();
    options.add("pool");
    Date[] maintenanceDates = new Date[1];
    maintenanceDates[0] = new Date();
    byte numFloors = 8;

    ApartmentBuilding building = new ApartmentBuilding (
      false,
      'B',
      12,
      396L,
      5.2,
      6.3f,
      numFloors,
      "Palisades",
      options,
      maintenanceDates
    );

    System.out.println("hashCode value: " + building.hashCode());
  }
} 

分享到:
评论

相关推荐

    java中的hashcode

    首先,从Java.lang.Object类中可以看到,hashCode方法是一个native方法,它的实现是由JVM提供的。JVM会将每个对象放入一个哈希表中,哈希表的键是对象的哈希码值。这样,当我们需要比较两个对象是否相等时,可以先...

    深入理解Java中HashCode方法

    同时,Java还提供了一些工具类和方法来帮助开发者实现hashCode方法,例如,Guava库中的Hashing类,它提供了多种hashCode算法,例如,MD5、SHA-1等。 Java中的hashCode方法是非常重要的,它直接影响着对象的比较和...

    javascript中实现兼容JAVA的hashCode算法代码分享

    1. **Java中的hashCode方法**:在Java中,对象的hashCode方法用于获取该对象的哈希码值,该值通常基于对象的内容计算得出。hashCode的目的是为了在使用如HashMap等哈希表数据结构时提高效率。Java中String类的...

    java中hashcode()和equals()方法详解

    在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将详细介绍这两个方法的工作原理、使用场景以及它们之间的关系...

    深入 HashCode 方法~

    - 对于不同的类,默认情况下,`hashCode()` 方法的实现可能会有所不同,但通常会依赖于对象的一些关键属性来生成一个整数值作为 `HashCode`。 2. **自定义类中的 HashCode 实现**: - 当我们自定义一个类时,通常...

    java中hashcode和equals的详解.pdf

    本文详细介绍了 Java 中的 hashCode 和 equals 方法,探讨了这两个方法的作用、实现机制和使用场景。通过对 hashCode 和 equals 方法的深入分析,我们可以更好地理解 Java 集合的实现原理和哈希表的工作机制。 一、...

    java中hashcode()和equals()的详解

    在Java编程语言中,`hashCode()`和`equals()`方法是对象身份验证的关键组成部分,它们主要用于对象的比较和哈希表(如HashMap、HashSet等)的操作。理解这两个方法的工作原理对于编写高效和可靠的代码至关重要。 ...

    equals与hashCode方法讲解

    equals 方法和 hashCode 方法是 Java 语言中两个重要的方法,它们都是在 Object 类中定义的。equals 方法用于比较两个对象是否相等,而 hashCode 方法用于返回对象的哈希码。 在 Java 的 Object 类中,equals 方法...

    浅谈Java中的hashcode方法(推荐)

    在Java编程语言中,`hashCode()`方法是`Object`类的一个重要成员,它用于生成对象的哈希码,这个哈希码是一个整数,通常用于优化基于哈希的集合操作,如`HashSet`、`HashMap`和`HashTable`。这些集合依赖于`hashCode...

    Java_重写equals()和hashCode()

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...

    JAVA_高级特性(hashCode,clone,比较器,Class反射,序列化)

    ### Java 高级特性详解 #### 一、`hashCode` ...正确地重写 `equals` 和 `hashCode` 方法、使用 `Comparator` 进行排序、利用反射机制和序列化技术,以及实现 `clone` 方法都是开发高质量 Java 应用程序的重要技能。

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...

    浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Object类中有一个方法:  public native int hashCode();...在Java中也一样,hashCode方法的主要作用是为了配合基于

    Java重写equals及hashcode方法流程解析

    hashCode方法是一个本地方法,无法在Java代码中实现。 一条重要的定理是:equals相同的对象,hashCode必然相同。这意味着,如果两个对象的equals方法返回true,那么它们的hashCode方法返回的值也必须相同。 三、...

    Java基础加强_ArrayList_HashSet的比较及Hashcode分析

    Hashcode是一个关键的概念,它是Java中的一个方法,用于将对象映射到一个整数值,通常用于哈希表的实现。每个对象都有一个唯一的哈希码,除非两个对象完全相等(equals()返回true),否则它们的哈希码必须不同。如果...

    如何生成一个合适的hashcode方法Java开发Java

    在Java编程语言中,`hashCode()`方法是每个对象都具备的一个关键组成部分,它与`equals()`方法一起工作,用于对象的比较和哈希表(如`HashMap`、`HashSet`等)的操作。本篇文章将深入探讨如何在Java中生成一个合适的...

    Java equals 方法与hashcode 方法的深入解析.rar

    在Java编程语言中,`equals()`方法和`hashCode()`方法是两个非常重要的概念,它们主要用于对象的比较和哈希表的高效运作。本解析将深入探讨这两个方法的用途、实现原理以及它们之间的关联。 首先,`equals()`方法是...

    Java 中HashCode作用_动力节点Java学院整理

    hashCode 的计算是通过调用对象的 hashCode() 方法来实现的,这个方法会返回一个整数值,这个整数值就是对象的 hashCode。 hashCode 的约定 在 Java 中,hashCode 有一些约定,例如: 1. 在一个应用程序执行期间...

    java中hashcode()和equals()的详解.docx

    ### Java中`hashCode()`与`...`hashCode()`和`equals()`方法在Java中的正确实现对于保证程序的正确性和性能都至关重要。开发者应当仔细考虑这些方法的实现细节,并遵循Java语言的规定,确保程序能够高效且正确地运行。

Global site tag (gtag.js) - Google Analytics