DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Hash Code Generator

05.04.2007
| 2707 views |
  • submit to reddit
        Simple hash code generator which allows hash codes for primitives and Java objects to be combined for a single object hash code with:

  new HashCode().hash(value1)
                .hash(value2)
                .hash(value3)
                .getHashCode();

This also supports hashing of arrays by recursively hashing all elements in the array.  Thanks to Item 8 in Joshua Bloch's "Effective Java" for the hash code theory:

public class HashCode {

    static final int DEFAULT_SEED = 23;
    static final int fODD_PRIME_NUMBER = 37;
    
    int hash;
    
    // ------------------------------------------------- Constructors
    
    /**
     * Constructor - creates a hash code object initialized with
     * the given seed value.
     */
    public HashCode(int seed) {
        this.hash = seed;
    }
    /**
     * Constructor - creates a hash code object initialized with
     * a default seed value.
     */
    public HashCode() {
        this(DEFAULT_SEED);
    }
    
    // ---------------------------------------------------- Accessors
    
    /**
     * Returns the hash code stored in the object
     */
    public int getHashCode() {
        return this.hash;
    }
    
    public String toString() {
        return String.valueOf(this.hash);
    }
    
    // ----------------------------------------------- Implementation
    
    /**
     * Adds the given value to the stored hash.  This is done by
     * multiplying the current hash by fODD_PRIME_NUMBER and then
     * adding the new value to it.
     */
    private void add(int value){
        this.hash = fODD_PRIME_NUMBER * this.hash + value;
    }
    
    //basic number types:
    
    public HashCode hash(int value) {
        add(value);
        return this;
    }
    public HashCode hash(long value) {
        add((int)( value ^ (value >>> 32) ));
        return this;
    }
    public HashCode hash(short value) {
        add((int)value);
        return this;
    }
    public HashCode hash(byte value) {
        add((int)value);
        return this;
    }
    public HashCode hash(float value ) {
        add(Float.floatToIntBits(value) );
        return this;
    }
    public HashCode hash(double value) {
        return hash(Double.doubleToLongBits(value));
    }
    
    //other primitives:
    
    public HashCode hash(boolean value) {
        add(value ? 1 : 0);
        return this;
    }
    public HashCode hash(char value) {
        add((int)value);
        return this;
    }
    
    //objects:
    
    /**
     * Hashes an object.  If this is null it will hash a value
     * of zero.  If it is an array it will recursively hash all
     * of the elements in the array.  For other objects it will
     * simply invoke their own hashCode() method.
     */
    public HashCode hash(Object obj) {
        
        if (obj == null) 
            add(0);
        
        else if (!isArray(obj) ) 
            add(obj.hashCode());
        
        else {
            //recursively hash all elements in the array
            int length = Array.getLength(obj);
            for (int i = 0; i < length; i++) {
                Object item = Array.get(obj, i);
                hash(item);
            }
        }
        
        return this;
    }
    
    // ----------------------------------------------- Static Methods
    
    /**
     * Returns true if the object is an array
     */
    private static boolean isArray(Object obj){
        return obj.getClass().isArray();
    }   
    
    /**
     * Returns a hash code for the given object.  This is offered
     * as a simplified method for:
     * 
     *   new HashCode().hash(obj).getHashCode()
     *   
     * Most notably, it allows for the quick and easy caching of
     * arrays.  It is not intended for hashing any arbitrary object
     * though.  For hashes beyond a single object property it is
     * better to instantiate the HashCode object and hash all
     * of the pertinent properties.
     */
    public static int hashArray(Object obj) {
        return new HashCode().hash(obj).getHashCode();
    }
    
    // ------------------------------------------------------ Testing
    
    public static void main(String [] args) {
        double [] a1 = new double [] {1,2,3,4,5,6};
        double [] a2 = new double [] {1,2,3,4,5,6};
        System.out.println(a1.hashCode());
        System.out.println(a2.hashCode());
        
        System.out.println(new HashCode().hash(a1));
        System.out.println(new HashCode().hash(a2));
    }
}