1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.harmony.misc; 19 20 /** 21 * This class is a convenience method to sequentially calculate hash code of the 22 * object based on the field values. The result depends on the order of elements 23 * appended. The exact formula is the same as for 24 * <code>java.util.List.hashCode</code>. 25 * 26 * If you need order independent hash code just summate, multiply or XOR all 27 * elements. 28 * 29 * <p> 30 * Suppose we have class: 31 * 32 * <pre><code> 33 * class Thing { 34 * long id; 35 * String name; 36 * float weight; 37 * } 38 * </code></pre> 39 * 40 * The hash code calculation can be expressed in 2 forms. 41 * 42 * <p> 43 * For maximum performance: 44 * 45 * <pre><code> 46 * public int hashCode() { 47 * int hashCode = HashCode.EMPTY_HASH_CODE; 48 * hashCode = HashCode.combine(hashCode, id); 49 * hashCode = HashCode.combine(hashCode, name); 50 * hashCode = HashCode.combine(hashCode, weight); 51 * return hashCode; 52 * } 53 * </code></pre> 54 * 55 * <p> 56 * For convenience: <code><pre> 57 * public int hashCode() { 58 * return new HashCode().append(id).append(name).append(weight).hashCode(); 59 * } 60 * </code></pre> 61 * 62 * @see java.util.List#hashCode() 63 */ 64 public final class HashCode { 65 /** 66 * The hashCode value before any data is appended, equals to 1. 67 * @see java.util.List#hashCode() 68 */ 69 public static final int EMPTY_HASH_CODE = 1; 70 71 private int hashCode = EMPTY_HASH_CODE; 72 73 /** 74 * Returns accumulated hashCode 75 */ 76 public final int hashCode() { 77 return hashCode; 78 } 79 80 /** 81 * Combines hashCode of previous elements sequence and value's hashCode. 82 * @param hashCode previous hashCode value 83 * @param value new element 84 * @return combined hashCode 85 */ 86 public static int combine(int hashCode, boolean value) { 87 int v = value ? 1231 : 1237; 88 return combine(hashCode, v); 89 } 90 91 /** 92 * Combines hashCode of previous elements sequence and value's hashCode. 93 * @param hashCode previous hashCode value 94 * @param value new element 95 * @return combined hashCode 96 */ 97 public static int combine(int hashCode, long value) { 98 int v = (int) (value ^ (value >>> 32)); 99 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 } 204