View Javadoc
1   /**
2    *    Copyright 2006-2016 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.mybatis.generator.internal.util;
17  
18  import java.lang.reflect.Array;
19  
20  /**
21   * This class is from javapractices.com:
22   * 
23   * http://www.javapractices.com/Topic28.cjp
24   * 
25   * Collected methods which allow easy implementation of <code>hashCode</code>.
26   * 
27   * Example use case:
28   * 
29   * <pre>
30   * public int hashCode() {
31   *     int result = HashCodeUtil.SEED;
32   *     //collect the contributions of various fields
33   *     result = HashCodeUtil.hash(result, fPrimitive);
34   *     result = HashCodeUtil.hash(result, fObject);
35   *     result = HashCodeUtil.hash(result, fArray);
36   *     return result;
37   * }
38   * </pre>
39   */
40  public final class HashCodeUtil {
41  
42      /**
43       * An initial value for a <code>hashCode</code>, to which is added
44       * contributions from fields. Using a non-zero value decreases collisons of
45       * <code>hashCode</code> values.
46       */
47      public static final int SEED = 23;
48  
49      /**
50       * booleans.
51       *
52       * @param aSeed
53       *            the a seed
54       * @param aBoolean
55       *            the a boolean
56       * @return the int
57       */
58      public static int hash(int aSeed, boolean aBoolean) {
59          return firstTerm(aSeed) + (aBoolean ? 1 : 0);
60      }
61  
62      /**
63       * chars.
64       *
65       * @param aSeed
66       *            the a seed
67       * @param aChar
68       *            the a char
69       * @return the int
70       */
71      public static int hash(int aSeed, char aChar) {
72          return firstTerm(aSeed) + aChar;
73      }
74  
75      /**
76       * ints.
77       *
78       * @param aSeed
79       *            the a seed
80       * @param aInt
81       *            the a int
82       * @return the int
83       */
84      public static int hash(int aSeed, int aInt) {
85          /*
86           * Implementation Note Note that byte and short are handled by this
87           * method, through implicit conversion.
88           */
89          return firstTerm(aSeed) + aInt;
90      }
91  
92      /**
93       * longs.
94       *
95       * @param aSeed
96       *            the a seed
97       * @param aLong
98       *            the a long
99       * @return the int
100      */
101     public static int hash(int aSeed, long aLong) {
102         return firstTerm(aSeed) + (int) (aLong ^ (aLong >>> 32));
103     }
104 
105     /**
106      * floats.
107      *
108      * @param aSeed
109      *            the a seed
110      * @param aFloat
111      *            the a float
112      * @return the int
113      */
114     public static int hash(int aSeed, float aFloat) {
115         return hash(aSeed, Float.floatToIntBits(aFloat));
116     }
117 
118     /**
119      * doubles.
120      *
121      * @param aSeed
122      *            the a seed
123      * @param aDouble
124      *            the a double
125      * @return the int
126      */
127     public static int hash(int aSeed, double aDouble) {
128         return hash(aSeed, Double.doubleToLongBits(aDouble));
129     }
130 
131     /**
132      * <code>aObject</code> is a possibly-null object field, and possibly an array.
133      * 
134      * If <code>aObject</code> is an array, then each element may be a primitive or a possibly-null object.
135      *
136      * @param aSeed
137      *            the a seed
138      * @param aObject
139      *            the a object
140      * @return the int
141      */
142     public static int hash(int aSeed, Object aObject) {
143         int result = aSeed;
144         if (aObject == null) {
145             result = hash(result, 0);
146         } else if (!isArray(aObject)) {
147             result = hash(result, aObject.hashCode());
148         } else {
149             int length = Array.getLength(aObject);
150             for (int idx = 0; idx < length; ++idx) {
151                 Object item = Array.get(aObject, idx);
152                 // recursive call!
153                 result = hash(result, item);
154             }
155         }
156         return result;
157     }
158 
159     // / PRIVATE ///
160     /** The odd prime number. */
161     private static final int fODD_PRIME_NUMBER = 37;
162 
163     /**
164      * First term.
165      *
166      * @param aSeed
167      *            the a seed
168      * @return the int
169      */
170     private static int firstTerm(int aSeed) {
171         return fODD_PRIME_NUMBER * aSeed;
172     }
173 
174     /**
175      * Checks if is array.
176      *
177      * @param aObject
178      *            the a object
179      * @return true, if is array
180      */
181     private static boolean isArray(Object aObject) {
182         return aObject.getClass().isArray();
183     }
184 }