Home | History | Annotate | Download | only in misc
      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