Hash Code Assist : Hash Code « Development Class « Java






Hash Code Assist

Hash Code Assist
      
//package org.streets.commons.assist;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * Assists in implementing {@link Object#hashCode()} methods.
 * </p>
 * 
 * <p>
 * This class enables a good <code>hashCode</code> method to be built for any
 * class. It follows the rules laid out in the book <a
 * href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
 * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually
 * quite difficult. This class aims to simplify the process.
 * </p>
 * 
 * <p>
 * All relevant fields from the object should be included in the
 * <code>hashCode</code> method. Derived fields may be excluded. In general, any
 * field used in the <code>equals</code> method must be used in the
 * <code>hashCode</code> method.
 * </p>
 * 
 * <p>
 * To use this class write code as follows:
 * </p>
 * 
 * <pre>
 * public class Person {
 *   String name;
 *   int age;
 *   boolean smoker;
 *   ...
 * 
 *   public int hashCode() {
 *     // you pick a hard-coded, randomly chosen, non-zero, odd number
 *     // ideally different for each class
 *     return new HashCodeBuilder(17, 37).
 *       append(name).
 *       append(age).
 *       append(smoker).
 *       toHashCode();
 *   }
 * }
 * </pre>
 * 
 * <p>
 * If required, the superclass <code>hashCode()</code> can be added using
 * {@link #appendSuper}.
 * </p>
 * 
 * <p>
 * Alternatively, there is a method that uses reflection to determine the fields
 * to test. Because these fields are usually private, the method,
 * <code>reflectionHashCode</code>, uses
 * <code>AccessibleObject.setAccessible</code> to change the visibility of the
 * fields. This will fail under a security manager, unless the appropriate
 * permissions are set up correctly. It is also slower than testing explicitly.
 * </p>
 * 
 * <p>
 * A typical invocation for this method would look like:
 * </p>
 * 
 * <pre>
 * public int hashCode() {
 *   return HashCodeBuilder.reflectionHashCode(this);
 * }
 * </pre>
 * 
 * @author Stephen Colebourne
 * @author Gary Gregory
 * @author Pete Gieser
 * @since 1.0
 * @version $Id: HashCodeBuilder.java 564070 2007-08-09 01:58:11Z bayard $
 */
public class HashCodeAssist {
  /**
   * <p>
   * A registry of objects used by reflection methods to detect cyclical
   * object references and avoid infinite loops.
   * </p>
   * 
   * @since 2.3
   */
  private static ThreadLocal<Set<Integer>> registry = new ThreadLocal<Set<Integer>>() {
    protected Set<Integer> initialValue() {
      // The HashSet implementation is not synchronized,
      // which is just what we need here.
      return new HashSet<Integer>();
    }
  };

  /**
   * <p>
   * Returns <code>true</code> if the registry contains the given object. Used
   * by the reflection methods to avoid infinite loops.
   * </p>
   * 
   * @param value
   *            The object to lookup in the registry.
   * @return boolean <code>true</code> if the registry contains the given
   *         object.
   * @since 2.3
   */
  static boolean isRegistered(Object value) {
    return registry.get().contains(toIdentityHashCodeInteger(value));
  }

  /**
   * <p>
   * Appends the fields and values defined by the given object of the given
   * <code>Class</code>.
   * </p>
   * 
   * @param object
   *            the object to append details of
   * @param clazz
   *            the class to append details of
   * @param builder
   *            the builder to append to
   * @param useTransients
   *            whether to use transient fields
   * @param excludeFields
   *            Collection of String field names to exclude from use in
   *            calculation of hash code
   */
  private static void reflectionAppend(Object object, Class<?> clazz,
      HashCodeAssist builder, boolean useTransients,
      String... excludeFields) {
    if (isRegistered(object)) {
      return;
    }
    try {
      register(object);
      Field[] fields = clazz.getDeclaredFields();
      List<String> excludedFieldList = excludeFields != null ? Arrays
          .asList(excludeFields) : Collections.EMPTY_LIST;
      AccessibleObject.setAccessible(fields, true);
      for (int i = 0; i < fields.length; i++) {
        Field field = fields[i];
        if (!excludedFieldList.contains(field.getName())
            && (field.getName().indexOf('$') == -1)
            && (useTransients || !Modifier.isTransient(field
                .getModifiers()))
            && (!Modifier.isStatic(field.getModifiers()))) {
          try {
            Object fieldValue = field.get(object);
            builder.append(fieldValue);
          } catch (IllegalAccessException e) {
            // this can't happen. Would get a Security exception
            // instead
            // throw a runtime exception in case the impossible
            // happens.
            throw new InternalError(
                "Unexpected IllegalAccessException");
          }
        }
      }
    } finally {
      unregister(object);
    }
  }

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <p>
   * Transient members will be not be used, as they are likely derived fields,
   * and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be tested. Superclass fields will be included.
   * </p>
   * 
   * <p>
   * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
   * these should be different for each class, however this is not vital.
   * Prime numbers are preferred, especially for the multiplier.
   * </p>
   * 
   * @param initialNonZeroOddNumber
   *            a non-zero, odd number used as the initial value
   * @param multiplierNonZeroOddNumber
   *            a non-zero, odd number used as the multiplier
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the Object is <code>null</code>
   * @throws IllegalArgumentException
   *             if the number is zero or even
   */
  public static int reflectionHashCode(int initialNonZeroOddNumber,
      int multiplierNonZeroOddNumber, Object object) {
    return reflectionHashCode(initialNonZeroOddNumber,
        multiplierNonZeroOddNumber, object, false, null);
  }

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <p>
   * If the TestTransients parameter is set to <code>true</code>, transient
   * members will be tested, otherwise they are ignored, as they are likely
   * derived fields, and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be tested. Superclass fields will be included.
   * </p>
   * 
   * <p>
   * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
   * these should be different for each class, however this is not vital.
   * Prime numbers are preferred, especially for the multiplier.
   * </p>
   * 
   * @param initialNonZeroOddNumber
   *            a non-zero, odd number used as the initial value
   * @param multiplierNonZeroOddNumber
   *            a non-zero, odd number used as the multiplier
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @param testTransients
   *            whether to include transient fields
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the Object is <code>null</code>
   * @throws IllegalArgumentException
   *             if the number is zero or even
   */
  public static int reflectionHashCode(int initialNonZeroOddNumber,
      int multiplierNonZeroOddNumber, Object object,
      boolean testTransients) {
    return reflectionHashCode(initialNonZeroOddNumber,
        multiplierNonZeroOddNumber, object, testTransients, null);
  }

  /**
   * Calls
   * {@link #reflectionHashCode(int, int, Object, boolean, Class, String[])}
   * with excludeFields set to <code>null</code>.
   * 
   * @param initialNonZeroOddNumber
   *            a non-zero, odd number used as the initial value
   * @param multiplierNonZeroOddNumber
   *            a non-zero, odd number used as the multiplier
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @param testTransients
   *            whether to include transient fields
   * @param reflectUpToClass
   *            the superclass to reflect up to (inclusive), may be
   *            <code>null</code>
   * @return int hash code
   */
  public static int reflectionHashCode(int initialNonZeroOddNumber,
      int multiplierNonZeroOddNumber, Object object,
      boolean testTransients, Class<?> reflectUpToClass) {
    return reflectionHashCode(initialNonZeroOddNumber,
        multiplierNonZeroOddNumber, object, testTransients,
        reflectUpToClass);
  }

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <p>
   * If the TestTransients parameter is set to <code>true</code>, transient
   * members will be tested, otherwise they are ignored, as they are likely
   * derived fields, and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be included. Superclass fields will be included up
   * to and including the specified superclass. A null superclass is treated
   * as java.lang.Object.
   * </p>
   * 
   * <p>
   * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
   * these should be different for each class, however this is not vital.
   * Prime numbers are preferred, especially for the multiplier.
   * </p>
   * 
   * @param initialNonZeroOddNumber
   *            a non-zero, odd number used as the initial value
   * @param multiplierNonZeroOddNumber
   *            a non-zero, odd number used as the multiplier
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @param testTransients
   *            whether to include transient fields
   * @param reflectUpToClass
   *            the superclass to reflect up to (inclusive), may be
   *            <code>null</code>
   * @param excludeFields
   *            array of field names to exclude from use in calculation of
   *            hash code
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the Object is <code>null</code>
   * @throws IllegalArgumentException
   *             if the number is zero or even
   * @since 2.0
   */
  public static int reflectionHashCode(int initialNonZeroOddNumber,
      int multiplierNonZeroOddNumber, Object object,
      boolean testTransients, Class<?> reflectUpToClass,
      String... excludeFields) {

    if (object == null) {
      throw new IllegalArgumentException(
          "The object to build a hash code for must not be null");
    }
    HashCodeAssist builder = new HashCodeAssist(initialNonZeroOddNumber,
        multiplierNonZeroOddNumber);
    Class<?> clazz = object.getClass();
    reflectionAppend(object, clazz, builder, testTransients, excludeFields);
    while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
      clazz = clazz.getSuperclass();
      reflectionAppend(object, clazz, builder, testTransients,
          excludeFields);
    }
    return builder.toHashCode();
  }

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * This constructor uses two hard coded choices for the constants needed to
   * build a hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <p>
   * Transient members will be not be used, as they are likely derived fields,
   * and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be tested. Superclass fields will be included.
   * </p>
   * 
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the object is <code>null</code>
   */
  public static int reflectionHashCode(Object object) {
    return reflectionHashCode(17, 37, object, false, null);
  }

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * This constructor uses two hard coded choices for the constants needed to
   * build a hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <P>
   * If the TestTransients parameter is set to <code>true</code>, transient
   * members will be tested, otherwise they are ignored, as they are likely
   * derived fields, and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be tested. Superclass fields will be included.
   * </p>
   * 
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @param testTransients
   *            whether to include transient fields
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the object is <code>null</code>
   */
  public static int reflectionHashCode(Object object, boolean testTransients) {
    return reflectionHashCode(17, 37, object, testTransients, null);
  }

  // -------------------------------------------------------------------------

  /**
   * <p>
   * This method uses reflection to build a valid hash code.
   * </p>
   * 
   * <p>
   * This constructor uses two hard coded choices for the constants needed to
   * build a hash code.
   * </p>
   * 
   * <p>
   * It uses <code>AccessibleObject.setAccessible</code> to gain access to
   * private fields. This means that it will throw a security exception if run
   * under a security manager, if the permissions are not set up correctly. It
   * is also not as efficient as testing explicitly.
   * </p>
   * 
   * <p>
   * Transient members will be not be used, as they are likely derived fields,
   * and not part of the value of the <code>Object</code>.
   * </p>
   * 
   * <p>
   * Static fields will not be tested. Superclass fields will be included.
   * </p>
   * 
   * @param object
   *            the Object to create a <code>hashCode</code> for
   * @param excludeFields
   *            array of field names to exclude from use in calculation of
   *            hash code
   * @return int hash code
   * @throws IllegalArgumentException
   *             if the object is <code>null</code>
   */
  public static int reflectionHashCode(Object object, String... excludeFields) {
    return reflectionHashCode(17, 37, object, false, null, excludeFields);
  }

  /**
   * <p>
   * Registers the given object. Used by the reflection methods to avoid
   * infinite loops.
   * </p>
   * 
   * @param value
   *            The object to register.
   */
  static void register(Object value) {
    registry.get().add(toIdentityHashCodeInteger(value));
  }

  /**
   * Returns an Integer for the given object's default hash code.
   * 
   * @see System#identityHashCode(Object)
   * @param value
   *            object for which the hashCode is to be calculated
   * @return Default int hash code
   */
  private static Integer toIdentityHashCodeInteger(Object value) {
    return new Integer(System.identityHashCode(value));
  }

  /**
   * <p>
   * Unregisters the given object.
   * </p>
   * 
   * <p>
   * Used by the reflection methods to avoid infinite loops.
   * 
   * @param value
   *            The object to unregister.
   * @since 2.3
   */
  static void unregister(Object value) {
    registry.get().remove(toIdentityHashCodeInteger(value));
  }

  /**
   * Constant to use in building the hashCode.
   */
  private final int iConstant;

  /**
   * Running total of the hashCode.
   */
  private int iTotal = 0;

  /**
   * <p>
   * Uses two hard coded choices for the constants needed to build a
   * <code>hashCode</code>.
   * </p>
   */
  public HashCodeAssist() {
    iConstant = 37;
    iTotal = 17;
  }

  /**
   * <p>
   * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
   * these should be different for each class, however this is not vital.
   * </p>
   * 
   * <p>
   * Prime numbers are preferred, especially for the multiplier.
   * </p>
   * 
   * @param initialNonZeroOddNumber
   *            a non-zero, odd number used as the initial value
   * @param multiplierNonZeroOddNumber
   *            a non-zero, odd number used as the multiplier
   * @throws IllegalArgumentException
   *             if the number is zero or even
   */
  public HashCodeAssist(int initialNonZeroOddNumber,
      int multiplierNonZeroOddNumber) {
    if (initialNonZeroOddNumber == 0) {
      throw new IllegalArgumentException(
          "HashCodeBuilder requires a non zero initial value");
    }
    if (initialNonZeroOddNumber % 2 == 0) {
      throw new IllegalArgumentException(
          "HashCodeBuilder requires an odd initial value");
    }
    if (multiplierNonZeroOddNumber == 0) {
      throw new IllegalArgumentException(
          "HashCodeBuilder requires a non zero multiplier");
    }
    if (multiplierNonZeroOddNumber % 2 == 0) {
      throw new IllegalArgumentException(
          "HashCodeBuilder requires an odd multiplier");
    }
    iConstant = multiplierNonZeroOddNumber;
    iTotal = initialNonZeroOddNumber;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>boolean</code>.
   * </p>
   * <p>
   * This adds <code>iConstant * 1</code> to the <code>hashCode</code> and not
   * a <code>1231</code> or <code>1237</code> as done in java.lang.Boolean.
   * This is in accordance with the <quote>Effective Java</quote> design.
   * </p>
   * 
   * @param value
   *            the boolean to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(boolean value) {
    iTotal = iTotal * iConstant + (value ? 0 : 1);
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>boolean</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(boolean[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  // -------------------------------------------------------------------------

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>byte</code>.
   * </p>
   * 
   * @param value
   *            the byte to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(byte value) {
    iTotal = iTotal * iConstant + value;
    return this;
  }

  // -------------------------------------------------------------------------

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>byte</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(byte[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>char</code>.
   * </p>
   * 
   * @param value
   *            the char to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(char value) {
    iTotal = iTotal * iConstant + value;
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>char</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(char[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>double</code>.
   * </p>
   * 
   * @param value
   *            the double to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(double value) {
    return append(Double.doubleToLongBits(value));
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>double</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(double[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>float</code>.
   * </p>
   * 
   * @param value
   *            the float to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(float value) {
    iTotal = iTotal * iConstant + Float.floatToIntBits(value);
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>float</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(float[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for an <code>int</code>.
   * </p>
   * 
   * @param value
   *            the int to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(int value) {
    iTotal = iTotal * iConstant + value;
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for an <code>int</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(int[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>long</code>.
   * </p>
   * <p>
   * 
   * @param value
   *            the long to add to the <code>hashCode</code>
   * @return this
   */
  // NOTE: This method uses >> and not >>> as Effective Java and
  // Long.hashCode do. Ideally we should switch to >>> at
  // some stage. There are backwards compat issues, so
  // that will have to wait for the time being. cf LANG-342.
  public HashCodeAssist append(long value) {
    iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>long</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(long[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for an <code>Object</code>.
   * </p>
   * 
   * @param object
   *            the Object to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(Object object) {
    if (object == null) {
      iTotal = iTotal * iConstant;

    } else {
      // 'Switch' on type of array, to dispatch to the correct handler
      // This handles multi dimensional arrays
      if (object instanceof long[]) {
        append((long[]) object);
      } else if (object instanceof int[]) {
        append((int[]) object);
      } else if (object instanceof short[]) {
        append((short[]) object);
      } else if (object instanceof char[]) {
        append((char[]) object);
      } else if (object instanceof byte[]) {
        append((byte[]) object);
      } else if (object instanceof double[]) {
        append((double[]) object);
      } else if (object instanceof float[]) {
        append((float[]) object);
      } else if (object instanceof boolean[]) {
        append((boolean[]) object);
      } else if (object instanceof Object[]) {
        // Not an array of primitives
        append((Object[]) object);
      } else {
        iTotal = iTotal * iConstant + object.hashCode();
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for an <code>Object</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(Object[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>short</code>.
   * </p>
   * 
   * @param value
   *            the short to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(short value) {
    iTotal = iTotal * iConstant + value;
    return this;
  }

  /**
   * <p>
   * Append a <code>hashCode</code> for a <code>short</code> array.
   * </p>
   * 
   * @param array
   *            the array to add to the <code>hashCode</code>
   * @return this
   */
  public HashCodeAssist append(short[] array) {
    if (array == null) {
      iTotal = iTotal * iConstant;
    } else {
      for (int i = 0; i < array.length; i++) {
        append(array[i]);
      }
    }
    return this;
  }

  /**
   * <p>
   * Adds the result of super.hashCode() to this builder.
   * </p>
   * 
   * @param superHashCode
   *            the result of calling <code>super.hashCode()</code>
   * @return this HashCodeBuilder, used to chain calls.
   * @since 2.0
   */
  public HashCodeAssist appendSuper(int superHashCode) {
    iTotal = iTotal * iConstant + superHashCode;
    return this;
  }

  /**
   * <p>
   * Return the computed <code>hashCode</code>.
   * </p>
   * 
   * @return <code>hashCode</code> based on the fields appended
   */
  public int toHashCode() {
    return iTotal;
  }

}

   
    
    
    
    
    
  








Related examples in the same category

1.Computing hash codes
2.A hash-code generator and a collection of static hash-code generation methods.
3.MD5 hash generator
4.Hash 32 String
5.Hash 64 String
6.MD5 hashing: Encodes a string
7.MD5 String
8.Hash Code BuilderHash Code Builder
9.HashCode generationHashCode generation
10.Get hash code for primitive data types
11.Return as hash code for the given object
12.Null Safe Hash Code
13.A very efficient java hash algorithm, based on the BuzHash algoritm
14.Easy implementation of hashCode
15.An implementation of the HMACT64 keyed hashing algorithm
16.Gets the hash code of an object returning zero when the object is null
17.Unify Hash
18.Secure Hash
19.FNV Hash
20.Jenkins Hash
21.Concurrent Cuckoo hashing using lock striping. Uses R/W locks for resizing. Exercise solution.
22.Concurrent Cuckoo hashing using lock striping.
23.encode Hex
24.Fowler/Noll/Vo hash algorhythm
25.Produces 32-bit hash for hash table lookup. (Jenkins Hash Function)
26.Key Value Hash
27.Paul Hsieh's Hash Function.
28.An extension of WeakReference that implements a sane equals and hashcode method.
29.Dual Key Hash Map
30.A hash map with int key and int values.
31.null Safe Equals and Hash
32.Generates a hash code for a given source code.
33.AtkinsonHash utility class implements the hash algorithm used by HyperCard's ask password command.
34.This is a very fast, non-cryptographic hash suitable for general hash-based lookup.
35.An advanced hash table supporting configurable garbage collection semantics of keys and values
36.Hash string