001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.misc;
019:
020: /**
021: * This class is a convenience method to sequentially calculate hash code of the
022: * object based on the field values. The result depends on the order of elements
023: * appended. The exact formula is the same as for
024: * <code>java.util.List.hashCode</code>.
025: *
026: * If you need order independent hash code just summate, multiply or XOR all
027: * elements.
028: *
029: * <p>
030: * Suppose we have class:
031: *
032: * <pre><code>
033: * class Thing {
034: * long id;
035: * String name;
036: * float weight;
037: * }
038: * </code></pre>
039: *
040: * The hash code calculation can be expressed in 2 forms.
041: *
042: * <p>
043: * For maximum performance:
044: *
045: * <pre><code>
046: * public int hashCode() {
047: * int hashCode = HashCode.EMPTY_HASH_CODE;
048: * hashCode = HashCode.combine(hashCode, id);
049: * hashCode = HashCode.combine(hashCode, name);
050: * hashCode = HashCode.combine(hashCode, weight);
051: * return hashCode;
052: * }
053: * </code></pre>
054: *
055: * <p>
056: * For convenience: <code><pre>
057: * public int hashCode() {
058: * return new HashCode().append(id).append(name).append(weight).hashCode();
059: * }
060: * </code></pre>
061: *
062: * @see java.util.List#hashCode()
063: */
064: public final class HashCode {
065: /**
066: * The hashCode value before any data is appended, equals to 1.
067: * @see java.util.List#hashCode()
068: */
069: public static final int EMPTY_HASH_CODE = 1;
070:
071: private int hashCode = EMPTY_HASH_CODE;
072:
073: /**
074: * Returns accumulated hashCode
075: */
076: public final int hashCode() {
077: return hashCode;
078: }
079:
080: /**
081: * Combines hashCode of previous elements sequence and value's hashCode.
082: * @param hashCode previous hashCode value
083: * @param value new element
084: * @return combined hashCode
085: */
086: public static int combine(int hashCode, boolean value) {
087: int v = value ? 1231 : 1237;
088: return combine(hashCode, v);
089: }
090:
091: /**
092: * Combines hashCode of previous elements sequence and value's hashCode.
093: * @param hashCode previous hashCode value
094: * @param value new element
095: * @return combined hashCode
096: */
097: public static int combine(int hashCode, long value) {
098: int v = (int) (value ^ (value >>> 32));
099: return combine(hashCode, v);
100: }
101:
102: /**
103: * Combines hashCode of previous elements sequence and value's hashCode.
104: * @param hashCode previous hashCode value
105: * @param value new element
106: * @return combined hashCode
107: */
108: public static int combine(int hashCode, float value) {
109: int v = Float.floatToIntBits(value);
110: return combine(hashCode, v);
111: }
112:
113: /**
114: * Combines hashCode of previous elements sequence and value's hashCode.
115: * @param hashCode previous hashCode value
116: * @param value new element
117: * @return combined hashCode
118: */
119: public static int combine(int hashCode, double value) {
120: long v = Double.doubleToLongBits(value);
121: return combine(hashCode, v);
122: }
123:
124: /**
125: * Combines hashCode of previous elements sequence and value's hashCode.
126: * @param hashCode previous hashCode value
127: * @param value new element
128: * @return combined hashCode
129: */
130: public static int combine(int hashCode, Object value) {
131: return combine(hashCode, value.hashCode());
132: }
133:
134: /**
135: * Combines hashCode of previous elements sequence and value's hashCode.
136: * @param hashCode previous hashCode value
137: * @param value new element
138: * @return combined hashCode
139: */
140: public static int combine(int hashCode, int value) {
141: return 31 * hashCode + value;
142: }
143:
144: /**
145: * Appends value's hashCode to the current hashCode.
146: * @param value new element
147: * @return this
148: */
149: public final HashCode append(int value) {
150: hashCode = combine(hashCode, value);
151: return this ;
152: }
153:
154: /**
155: * Appends value's hashCode to the current hashCode.
156: * @param value new element
157: * @return this
158: */
159: public final HashCode append(long value) {
160: hashCode = combine(hashCode, value);
161: return this ;
162: }
163:
164: /**
165: * Appends value's hashCode to the current hashCode.
166: * @param value new element
167: * @return this
168: */
169: public final HashCode append(float value) {
170: hashCode = combine(hashCode, value);
171: return this ;
172: }
173:
174: /**
175: * Appends value's hashCode to the current hashCode.
176: * @param value new element
177: * @return this
178: */
179: public final HashCode append(double value) {
180: hashCode = combine(hashCode, value);
181: return this ;
182: }
183:
184: /**
185: * Appends value's hashCode to the current hashCode.
186: * @param value new element
187: * @return this
188: */
189: public final HashCode append(boolean value) {
190: hashCode = combine(hashCode, value);
191: return this ;
192: }
193:
194: /**
195: * Appends value's hashCode to the current hashCode.
196: * @param value new element
197: * @return this
198: */
199: public final HashCode append(Object value) {
200: hashCode = combine(hashCode, value);
201: return this;
202: }
203: }
|