Project Report: fawkez

Packagesummary org.jcoderz.commons.util

org.jcoderz.commons.util.HashCodeUtil

LineHitsNoteSource
1  /*
2   * $Id: HashCodeUtil.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.util;
34  
35  
36  import java.lang.reflect.Array;
37  
38  
39  /**
40   * Collected methods which allow easy implementation of
41   * <code>hashCode</code>. Example use case:
42   *
43   * <pre>
44   * public int hashCode ()
45   * {
46   *    int result = HashCodeUtil.SEED;
47   *    //collect the contributions of various fields
48   *    result = HashCodeUtil.hash(result, mPrimitive);
49   *    result = HashCodeUtil.hash(result, mObject);
50   *    result = HashCodeUtil.hash(result, mArray);
51   *    return result;
52   * }
53   * </pre>
54   *
55   * @author Michael Griffel
56   */
57  public final class HashCodeUtil
58  {
59     /**
60      * An initial value for a <code>hashCode</code>, to which is added
61      * contributions from fields. Using a non-zero value decreases
62      * collisons of <code>hashCode</code> values.
63      */
64     public static final int SEED = 23;
65  
66     /**
67      * An factor that is used in the first term to multiply the <i>old</i>
68      * hash code value.
69      */
70     private static final int ODD_PRIME_NUMBER = 37;
71  
72     /**
73      * No instances allowed.
74      */
75     private HashCodeUtil ()
760    {
77        // Utility class -- provides only static helper methods.
780    }
79  
80     /**
81      * Constructs a new seed using the given Boolean and the previous seed.
82      * @param aSeed the previous seed value.
83      * @param aBoolean the Boolean that should be added to the new seed.
84      * @return the new seed.
85      */
86     public static int hash (int aSeed, boolean aBoolean)
87     {
88100       return firstTerm(aSeed) + (aBoolean ? 1 : 0);
89     }
90  
91     /**
92      * Constructs a new seed using the given boolean and the previous seed.
93      * @param aSeed the previous seed value.
94      * @param aChar the character that should be added to the new seed.
95      * @return the new seed.
96      */
97     public static int hash (int aSeed, char aChar)
98     {
99100       return firstTerm(aSeed) + aChar;
100     }
101  
102     /**
103      * Constructs a new seed using the given integer and the previous seed.
104      * Note that byte and short are handled by this method,
105      * through implicit conversion.
106      * @param aSeed the previous seed value.
107      * @param aInt the integer that should be added to the new seed.
108      * @return the new seed.
109      */
110     public static int hash (int aSeed, int aInt)
111     {
112100       return firstTerm(aSeed) + aInt;
113     }
114  
115     /**
116      * Constructs a new seed using the given long and the previous seed.
117      * @param aSeed the previous seed value.
118      * @param aLong the long value that should be added to the new seed.
119      * @return the new seed.
120      */
121     public static int hash (int aSeed, long aLong)
122     {
123100       return firstTerm(aSeed) + (int) (aLong
124              ^ (aLong >>> Constants.BITS_PER_INTEGER));
125     }
126  
127     /**
128      * Constructs a new seed using the given float and the previous seed.
129      * @param aSeed the previous seed value.
130      * @param aFloat the float that should be added to the new seed.
131      * @return the new seed.
132      */
133     public static int hash (int aSeed, float aFloat)
134     {
135100       return hash(aSeed, Float.floatToIntBits(aFloat));
136     }
137  
138     /**
139      * Constructs a new seed using the given double and the previous seed.
140      * @param aSeed the previous seed value.
141      * @param aDouble the double that should be added to the new seed.
142      * @return the new seed.
143      */
144     public static int hash (int aSeed, double aDouble)
145     {
146100       return hash(aSeed, Double.doubleToLongBits(aDouble));
147     }
148  
149     /**
150      * Constructs a new seed using the given object and the previous seed.
151      *
152      * <code>aObject</code> is a possibly-null object field, and possibly
153      * an array. If <code>aObject</code> is an array, then each element
154      * may be a primitive or a possibly-null object.
155      *
156      * @param aSeed the previous seed value.
157      * @param aObject the integer that should be added to the new seed.
158      * @return the new seed.
159      */
160     public static int hash (int aSeed, Object aObject)
161     {
162100       int result = aSeed;
163  
164100       if (aObject == null)
165        {
166100          result = hash(result, 0);
167        }
168100       else if (!isArray(aObject))
169        {
170100          result = hash(result, aObject.hashCode());
171        }
172        else
173        {
174100          final int length = Array.getLength(aObject);
175100          for (int i = 0; i < length; ++i)
176           {
177100             final Object item = Array.get(aObject, i);
178              //recursive call!
179100             result = hash(result, item);
180           }
181100          result = hash(result, length);
182        }
183100       return result;
184     }
185  
186     /**
187      * Calculates the first part (term) of the seed.
188      * @param aSeed the old seed value.
189      * @return the part of the new seed.
190      */
191     private static int firstTerm (int aSeed)
192     {
193100       return ODD_PRIME_NUMBER * aSeed;
194     }
195  
196     /**
197      * Returns <code>true</code> if the given object represents an array.
198      * @return <code>true</code> if the given object represents an array;
199      *       <code>false</code> otherwise.
200      */
201     private static boolean isArray (Object aObject)
202     {
203100       return aObject.getClass().isArray();
204     }
205  }

Findings in this File