HashCodeBuilder.java

  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. package org.apache.commons.lang3.builder;

  18. import java.lang.reflect.AccessibleObject;
  19. import java.lang.reflect.Field;
  20. import java.lang.reflect.Modifier;
  21. import java.util.Collection;
  22. import java.util.Comparator;
  23. import java.util.HashSet;
  24. import java.util.Objects;
  25. import java.util.Set;

  26. import org.apache.commons.lang3.ArraySorter;
  27. import org.apache.commons.lang3.ArrayUtils;
  28. import org.apache.commons.lang3.ObjectUtils;
  29. import org.apache.commons.lang3.Validate;

  30. /**
  31.  * Assists in implementing {@link Object#hashCode()} methods.
  32.  *
  33.  * <p>
  34.  * This class enables a good {@code hashCode} method to be built for any class. It follows the rules laid out in
  35.  * the book <a href="https://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a
  36.  * good {@code hashCode} method is actually quite difficult. This class aims to simplify the process.
  37.  * </p>
  38.  *
  39.  * <p>
  40.  * The following is the approach taken. When appending a data field, the current total is multiplied by the
  41.  * multiplier then a relevant value
  42.  * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
  43.  * appending the integer 45 will create a hash code of 674, namely 17 * 37 + 45.
  44.  * </p>
  45.  *
  46.  * <p>
  47.  * All relevant fields from the object should be included in the {@code hashCode} method. Derived fields may be
  48.  * excluded. In general, any field used in the {@code equals} method must be used in the {@code hashCode}
  49.  * method.
  50.  * </p>
  51.  *
  52.  * <p>
  53.  * To use this class write code as follows:
  54.  * </p>
  55.  *
  56.  * <pre>
  57.  * public class Person {
  58.  *   String name;
  59.  *   int age;
  60.  *   boolean smoker;
  61.  *   ...
  62.  *
  63.  *   public int hashCode() {
  64.  *     // you pick a hard-coded, randomly chosen, non-zero, odd number
  65.  *     // ideally different for each class
  66.  *     return new HashCodeBuilder(17, 37).
  67.  *       append(name).
  68.  *       append(age).
  69.  *       append(smoker).
  70.  *       toHashCode();
  71.  *   }
  72.  * }
  73.  * </pre>
  74.  *
  75.  * <p>
  76.  * If required, the superclass {@code hashCode()} can be added using {@link #appendSuper}.
  77.  * </p>
  78.  *
  79.  * <p>
  80.  * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
  81.  * usually private, the method, {@code reflectionHashCode}, uses {@code AccessibleObject.setAccessible}
  82.  * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
  83.  * are set up correctly. It is also slower than testing explicitly.
  84.  * </p>
  85.  *
  86.  * <p>
  87.  * A typical invocation for this method would look like:
  88.  * </p>
  89.  *
  90.  * <pre>
  91.  * public int hashCode() {
  92.  *   return HashCodeBuilder.reflectionHashCode(this);
  93.  * }
  94.  * </pre>
  95.  *
  96.  * <p>The {@link HashCodeExclude} annotation can be used to exclude fields from being
  97.  * used by the {@code reflectionHashCode} methods.</p>
  98.  *
  99.  * @since 1.0
  100.  */
  101. public class HashCodeBuilder implements Builder<Integer> {
  102.     /**
  103.      * The default initial value to use in reflection hash code building.
  104.      */
  105.     private static final int DEFAULT_INITIAL_VALUE = 17;

  106.     /**
  107.      * The default multiplier value to use in reflection hash code building.
  108.      */
  109.     private static final int DEFAULT_MULTIPLIER_VALUE = 37;

  110.     /**
  111.      * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
  112.      *
  113.      * @since 2.3
  114.      */
  115.     private static final ThreadLocal<Set<IDKey>> REGISTRY = ThreadLocal.withInitial(HashSet::new);

  116.     /*
  117.      * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
  118.      * we are in the process of calculating.
  119.      *
  120.      * So we generate a one-to-one mapping from the original object to a new object.
  121.      *
  122.      * Now HashSet uses equals() to determine if two elements with the same hash code really
  123.      * are equal, so we also need to ensure that the replacement objects are only equal
  124.      * if the original objects are identical.
  125.      *
  126.      * The original implementation (2.4 and before) used the System.identityHashCode()
  127.      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
  128.      *
  129.      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
  130.      * to disambiguate the duplicate ids.
  131.      */

  132.     /**
  133.      * Returns the registry of objects being traversed by the reflection methods in the current thread.
  134.      *
  135.      * @return Set the registry of objects being traversed
  136.      * @since 2.3
  137.      */
  138.     static Set<IDKey> getRegistry() {
  139.         return REGISTRY.get();
  140.     }

  141.     /**
  142.      * Returns {@code true} if the registry contains the given object. Used by the reflection methods to avoid
  143.      * infinite loops.
  144.      *
  145.      * @param value
  146.      *            The object to lookup in the registry.
  147.      * @return boolean {@code true} if the registry contains the given object.
  148.      * @since 2.3
  149.      */
  150.     static boolean isRegistered(final Object value) {
  151.         final Set<IDKey> registry = getRegistry();
  152.         return registry != null && registry.contains(new IDKey(value));
  153.     }

  154.     /**
  155.      * Appends the fields and values defined by the given object of the given {@link Class}.
  156.      *
  157.      * @param object
  158.      *            the object to append details of
  159.      * @param clazz
  160.      *            the class to append details of
  161.      * @param builder
  162.      *            the builder to append to
  163.      * @param useTransients
  164.      *            whether to use transient fields
  165.      * @param excludeFields
  166.      *            Collection of String field names to exclude from use in calculation of hash code
  167.      */
  168.     private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients,
  169.             final String[] excludeFields) {
  170.         if (isRegistered(object)) {
  171.             return;
  172.         }
  173.         try {
  174.             register(object);
  175.             // The elements in the returned array are not sorted and are not in any particular order.
  176.             final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
  177.             AccessibleObject.setAccessible(fields, true);
  178.             for (final Field field : fields) {
  179.                 if (!ArrayUtils.contains(excludeFields, field.getName())
  180.                     && !field.getName().contains("$")
  181.                     && (useTransients || !Modifier.isTransient(field.getModifiers()))
  182.                     && !Modifier.isStatic(field.getModifiers())
  183.                     && !field.isAnnotationPresent(HashCodeExclude.class)) {
  184.                     builder.append(Reflection.getUnchecked(field, object));
  185.                 }
  186.             }
  187.         } finally {
  188.             unregister(object);
  189.         }
  190.     }

  191.     /**
  192.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  193.      *
  194.      * <p>
  195.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  196.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  197.      * also not as efficient as testing explicitly.
  198.      * </p>
  199.      *
  200.      * <p>
  201.      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
  202.      * {@link Object}.
  203.      * </p>
  204.      *
  205.      * <p>
  206.      * Static fields will not be tested. Superclass fields will be included.
  207.      * </p>
  208.      *
  209.      * <p>
  210.      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
  211.      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
  212.      * </p>
  213.      *
  214.      * @param initialNonZeroOddNumber
  215.      *            a non-zero, odd number used as the initial value. This will be the returned
  216.      *            value if no fields are found to include in the hash code
  217.      * @param multiplierNonZeroOddNumber
  218.      *            a non-zero, odd number used as the multiplier
  219.      * @param object
  220.      *            the Object to create a {@code hashCode} for
  221.      * @return int hash code
  222.      * @throws NullPointerException
  223.      *             if the Object is {@code null}
  224.      * @throws IllegalArgumentException
  225.      *             if the number is zero or even
  226.      *
  227.      * @see HashCodeExclude
  228.      */
  229.     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
  230.         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
  231.     }

  232.     /**
  233.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  234.      *
  235.      * <p>
  236.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  237.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  238.      * also not as efficient as testing explicitly.
  239.      * </p>
  240.      *
  241.      * <p>
  242.      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
  243.      * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
  244.      * </p>
  245.      *
  246.      * <p>
  247.      * Static fields will not be tested. Superclass fields will be included.
  248.      * </p>
  249.      *
  250.      * <p>
  251.      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
  252.      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
  253.      * </p>
  254.      *
  255.      * @param initialNonZeroOddNumber
  256.      *            a non-zero, odd number used as the initial value. This will be the returned
  257.      *            value if no fields are found to include in the hash code
  258.      * @param multiplierNonZeroOddNumber
  259.      *            a non-zero, odd number used as the multiplier
  260.      * @param object
  261.      *            the Object to create a {@code hashCode} for
  262.      * @param testTransients
  263.      *            whether to include transient fields
  264.      * @return int hash code
  265.      * @throws NullPointerException
  266.      *             if the Object is {@code null}
  267.      * @throws IllegalArgumentException
  268.      *             if the number is zero or even
  269.      *
  270.      * @see HashCodeExclude
  271.      */
  272.     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
  273.             final boolean testTransients) {
  274.         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
  275.     }

  276.     /**
  277.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  278.      *
  279.      * <p>
  280.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  281.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  282.      * also not as efficient as testing explicitly.
  283.      * </p>
  284.      *
  285.      * <p>
  286.      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
  287.      * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
  288.      * </p>
  289.      *
  290.      * <p>
  291.      * Static fields will not be included. Superclass fields will be included up to and including the specified
  292.      * superclass. A null superclass is treated as java.lang.Object.
  293.      * </p>
  294.      *
  295.      * <p>
  296.      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
  297.      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
  298.      * </p>
  299.      *
  300.      * @param <T>
  301.      *            the type of the object involved
  302.      * @param initialNonZeroOddNumber
  303.      *            a non-zero, odd number used as the initial value. This will be the returned
  304.      *            value if no fields are found to include in the hash code
  305.      * @param multiplierNonZeroOddNumber
  306.      *            a non-zero, odd number used as the multiplier
  307.      * @param object
  308.      *            the Object to create a {@code hashCode} for
  309.      * @param testTransients
  310.      *            whether to include transient fields
  311.      * @param reflectUpToClass
  312.      *            the superclass to reflect up to (inclusive), may be {@code null}
  313.      * @param excludeFields
  314.      *            array of field names to exclude from use in calculation of hash code
  315.      * @return int hash code
  316.      * @throws NullPointerException
  317.      *             if the Object is {@code null}
  318.      * @throws IllegalArgumentException
  319.      *             if the number is zero or even
  320.      *
  321.      * @see HashCodeExclude
  322.      * @since 2.0
  323.      */
  324.     public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
  325.             final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
  326.         Objects.requireNonNull(object, "object");
  327.         final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
  328.         Class<?> clazz = object.getClass();
  329.         reflectionAppend(object, clazz, builder, testTransients, excludeFields);
  330.         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
  331.             clazz = clazz.getSuperclass();
  332.             reflectionAppend(object, clazz, builder, testTransients, excludeFields);
  333.         }
  334.         return builder.toHashCode();
  335.     }

  336.     /**
  337.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  338.      *
  339.      * <p>
  340.      * This constructor uses two hard coded choices for the constants needed to build a hash code.
  341.      * </p>
  342.      *
  343.      * <p>
  344.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  345.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  346.      * also not as efficient as testing explicitly.
  347.      * </p>
  348.      *
  349.      * <p>
  350.      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
  351.      * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
  352.      * </p>
  353.      *
  354.      * <p>
  355.      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
  356.      * in the hash code, the result of this method will be constant.
  357.      * </p>
  358.      *
  359.      * @param object
  360.      *            the Object to create a {@code hashCode} for
  361.      * @param testTransients
  362.      *            whether to include transient fields
  363.      * @return int hash code
  364.      * @throws NullPointerException
  365.      *             if the object is {@code null}
  366.      *
  367.      * @see HashCodeExclude
  368.      */
  369.     public static int reflectionHashCode(final Object object, final boolean testTransients) {
  370.         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
  371.                 testTransients, null);
  372.     }

  373.     /**
  374.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  375.      *
  376.      * <p>
  377.      * This constructor uses two hard coded choices for the constants needed to build a hash code.
  378.      * </p>
  379.      *
  380.      * <p>
  381.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  382.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  383.      * also not as efficient as testing explicitly.
  384.      * </p>
  385.      *
  386.      * <p>
  387.      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
  388.      * {@link Object}.
  389.      * </p>
  390.      *
  391.      * <p>
  392.      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
  393.      * in the hash code, the result of this method will be constant.
  394.      * </p>
  395.      *
  396.      * @param object
  397.      *            the Object to create a {@code hashCode} for
  398.      * @param excludeFields
  399.      *            Collection of String field names to exclude from use in calculation of hash code
  400.      * @return int hash code
  401.      * @throws NullPointerException
  402.      *             if the object is {@code null}
  403.      *
  404.      * @see HashCodeExclude
  405.      */
  406.     public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
  407.         return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
  408.     }

  409.     /**
  410.      * Uses reflection to build a valid hash code from the fields of {@code object}.
  411.      *
  412.      * <p>
  413.      * This constructor uses two hard coded choices for the constants needed to build a hash code.
  414.      * </p>
  415.      *
  416.      * <p>
  417.      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
  418.      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
  419.      * also not as efficient as testing explicitly.
  420.      * </p>
  421.      *
  422.      * <p>
  423.      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
  424.      * {@link Object}.
  425.      * </p>
  426.      *
  427.      * <p>
  428.      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
  429.      * in the hash code, the result of this method will be constant.
  430.      * </p>
  431.      *
  432.      * @param object
  433.      *            the Object to create a {@code hashCode} for
  434.      * @param excludeFields
  435.      *            array of field names to exclude from use in calculation of hash code
  436.      * @return int hash code
  437.      * @throws NullPointerException
  438.      *             if the object is {@code null}
  439.      *
  440.      * @see HashCodeExclude
  441.      */
  442.     public static int reflectionHashCode(final Object object, final String... excludeFields) {
  443.         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
  444.                 null, excludeFields);
  445.     }

  446.     /**
  447.      * Registers the given object. Used by the reflection methods to avoid infinite loops.
  448.      *
  449.      * @param value
  450.      *            The object to register.
  451.      */
  452.     private static void register(final Object value) {
  453.         getRegistry().add(new IDKey(value));
  454.     }

  455.     /**
  456.      * Unregisters the given object.
  457.      *
  458.      * <p>
  459.      * Used by the reflection methods to avoid infinite loops.
  460.      * </p>
  461.      *
  462.      * @param value
  463.      *            The object to unregister.
  464.      * @since 2.3
  465.      */
  466.     private static void unregister(final Object value) {
  467.         final Set<IDKey> registry = getRegistry();
  468.         registry.remove(new IDKey(value));
  469.         if (registry.isEmpty()) {
  470.             REGISTRY.remove();
  471.         }
  472.     }

  473.     /**
  474.      * Constant to use in building the hashCode.
  475.      */
  476.     private final int iConstant;

  477.     /**
  478.      * Running total of the hashCode.
  479.      */
  480.     private int iTotal;

  481.     /**
  482.      * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
  483.      */
  484.     public HashCodeBuilder() {
  485.         iConstant = 37;
  486.         iTotal = 17;
  487.     }

  488.     /**
  489.      * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
  490.      * however this is not vital.
  491.      *
  492.      * <p>
  493.      * Prime numbers are preferred, especially for the multiplier.
  494.      * </p>
  495.      *
  496.      * @param initialOddNumber
  497.      *            an odd number used as the initial value
  498.      * @param multiplierOddNumber
  499.      *            an odd number used as the multiplier
  500.      * @throws IllegalArgumentException
  501.      *             if the number is even
  502.      */
  503.     public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
  504.         Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
  505.         Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
  506.         iConstant = multiplierOddNumber;
  507.         iTotal = initialOddNumber;
  508.     }

  509.     /**
  510.      * Append a {@code hashCode} for a {@code boolean}.
  511.      *
  512.      * <p>
  513.      * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
  514.      * </p>
  515.      * <p>
  516.      * This is in contrast to the standard {@link Boolean#hashCode()} handling, which computes
  517.      * a {@code hashCode} value of {@code 1231} for {@link Boolean} instances
  518.      * that represent {@code true} or {@code 1237} for {@link Boolean} instances
  519.      * that represent {@code false}.
  520.      * </p>
  521.      * <p>
  522.      * This is in accordance with the <em>Effective Java</em> design.
  523.      * </p>
  524.      *
  525.      * @param value
  526.      *            the boolean to add to the {@code hashCode}
  527.      * @return {@code this} instance.
  528.      */
  529.     public HashCodeBuilder append(final boolean value) {
  530.         iTotal = iTotal * iConstant + (value ? 0 : 1);
  531.         return this;
  532.     }

  533.     /**
  534.      * Append a {@code hashCode} for a {@code boolean} array.
  535.      *
  536.      * @param array
  537.      *            the array to add to the {@code hashCode}
  538.      * @return {@code this} instance.
  539.      */
  540.     public HashCodeBuilder append(final boolean[] array) {
  541.         if (array == null) {
  542.             iTotal = iTotal * iConstant;
  543.         } else {
  544.             for (final boolean element : array) {
  545.                 append(element);
  546.             }
  547.         }
  548.         return this;
  549.     }

  550.     /**
  551.      * Append a {@code hashCode} for a {@code byte}.
  552.      *
  553.      * @param value
  554.      *            the byte to add to the {@code hashCode}
  555.      * @return {@code this} instance.
  556.      */
  557.     public HashCodeBuilder append(final byte value) {
  558.         iTotal = iTotal * iConstant + value;
  559.         return this;
  560.     }

  561.     /**
  562.      * Append a {@code hashCode} for a {@code byte} array.
  563.      *
  564.      * @param array
  565.      *            the array to add to the {@code hashCode}
  566.      * @return {@code this} instance.
  567.      */
  568.     public HashCodeBuilder append(final byte[] array) {
  569.         if (array == null) {
  570.             iTotal = iTotal * iConstant;
  571.         } else {
  572.             for (final byte element : array) {
  573.                 append(element);
  574.             }
  575.         }
  576.         return this;
  577.     }

  578.     /**
  579.      * Append a {@code hashCode} for a {@code char}.
  580.      *
  581.      * @param value
  582.      *            the char to add to the {@code hashCode}
  583.      * @return {@code this} instance.
  584.      */
  585.     public HashCodeBuilder append(final char value) {
  586.         iTotal = iTotal * iConstant + value;
  587.         return this;
  588.     }

  589.     /**
  590.      * Append a {@code hashCode} for a {@code char} array.
  591.      *
  592.      * @param array
  593.      *            the array to add to the {@code hashCode}
  594.      * @return {@code this} instance.
  595.      */
  596.     public HashCodeBuilder append(final char[] array) {
  597.         if (array == null) {
  598.             iTotal = iTotal * iConstant;
  599.         } else {
  600.             for (final char element : array) {
  601.                 append(element);
  602.             }
  603.         }
  604.         return this;
  605.     }

  606.     /**
  607.      * Append a {@code hashCode} for a {@code double}.
  608.      *
  609.      * @param value
  610.      *            the double to add to the {@code hashCode}
  611.      * @return {@code this} instance.
  612.      */
  613.     public HashCodeBuilder append(final double value) {
  614.         return append(Double.doubleToLongBits(value));
  615.     }

  616.     /**
  617.      * Append a {@code hashCode} for a {@code double} array.
  618.      *
  619.      * @param array
  620.      *            the array to add to the {@code hashCode}
  621.      * @return {@code this} instance.
  622.      */
  623.     public HashCodeBuilder append(final double[] array) {
  624.         if (array == null) {
  625.             iTotal = iTotal * iConstant;
  626.         } else {
  627.             for (final double element : array) {
  628.                 append(element);
  629.             }
  630.         }
  631.         return this;
  632.     }

  633.     /**
  634.      * Append a {@code hashCode} for a {@code float}.
  635.      *
  636.      * @param value
  637.      *            the float to add to the {@code hashCode}
  638.      * @return {@code this} instance.
  639.      */
  640.     public HashCodeBuilder append(final float value) {
  641.         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
  642.         return this;
  643.     }

  644.     /**
  645.      * Append a {@code hashCode} for a {@code float} array.
  646.      *
  647.      * @param array
  648.      *            the array to add to the {@code hashCode}
  649.      * @return {@code this} instance.
  650.      */
  651.     public HashCodeBuilder append(final float[] array) {
  652.         if (array == null) {
  653.             iTotal = iTotal * iConstant;
  654.         } else {
  655.             for (final float element : array) {
  656.                 append(element);
  657.             }
  658.         }
  659.         return this;
  660.     }

  661.     /**
  662.      * Append a {@code hashCode} for an {@code int}.
  663.      *
  664.      * @param value
  665.      *            the int to add to the {@code hashCode}
  666.      * @return {@code this} instance.
  667.      */
  668.     public HashCodeBuilder append(final int value) {
  669.         iTotal = iTotal * iConstant + value;
  670.         return this;
  671.     }

  672.     /**
  673.      * Append a {@code hashCode} for an {@code int} array.
  674.      *
  675.      * @param array
  676.      *            the array to add to the {@code hashCode}
  677.      * @return {@code this} instance.
  678.      */
  679.     public HashCodeBuilder append(final int[] array) {
  680.         if (array == null) {
  681.             iTotal = iTotal * iConstant;
  682.         } else {
  683.             for (final int element : array) {
  684.                 append(element);
  685.             }
  686.         }
  687.         return this;
  688.     }

  689.     /**
  690.      * Append a {@code hashCode} for a {@code long}.
  691.      *
  692.      * @param value
  693.      *            the long to add to the {@code hashCode}
  694.      * @return {@code this} instance.
  695.      */
  696.     // NOTE: This method uses >> and not >>> as Effective Java and
  697.     //       Long.hashCode do. Ideally we should switch to >>> at
  698.     //       some stage. There are backwards compat issues, so
  699.     //       that will have to wait for the time being. cf LANG-342.
  700.     public HashCodeBuilder append(final long value) {
  701.         iTotal = iTotal * iConstant + (int) (value ^ value >> 32);
  702.         return this;
  703.     }

  704.     /**
  705.      * Append a {@code hashCode} for a {@code long} array.
  706.      *
  707.      * @param array
  708.      *            the array to add to the {@code hashCode}
  709.      * @return {@code this} instance.
  710.      */
  711.     public HashCodeBuilder append(final long[] array) {
  712.         if (array == null) {
  713.             iTotal = iTotal * iConstant;
  714.         } else {
  715.             for (final long element : array) {
  716.                 append(element);
  717.             }
  718.         }
  719.         return this;
  720.     }

  721.     /**
  722.      * Append a {@code hashCode} for an {@link Object}.
  723.      *
  724.      * @param object
  725.      *            the Object to add to the {@code hashCode}
  726.      * @return {@code this} instance.
  727.      */
  728.     public HashCodeBuilder append(final Object object) {
  729.         if (object == null) {
  730.             iTotal = iTotal * iConstant;

  731.         } else if (ObjectUtils.isArray(object)) {
  732.             // factor out array case in order to keep method small enough
  733.             // to be inlined
  734.             appendArray(object);
  735.         } else {
  736.             iTotal = iTotal * iConstant + object.hashCode();
  737.         }
  738.         return this;
  739.     }

  740.     /**
  741.      * Append a {@code hashCode} for an {@link Object} array.
  742.      *
  743.      * @param array
  744.      *            the array to add to the {@code hashCode}
  745.      * @return {@code this} instance.
  746.      */
  747.     public HashCodeBuilder append(final Object[] array) {
  748.         if (array == null) {
  749.             iTotal = iTotal * iConstant;
  750.         } else {
  751.             for (final Object element : array) {
  752.                 append(element);
  753.             }
  754.         }
  755.         return this;
  756.     }

  757.     /**
  758.      * Append a {@code hashCode} for a {@code short}.
  759.      *
  760.      * @param value
  761.      *            the short to add to the {@code hashCode}
  762.      * @return {@code this} instance.
  763.      */
  764.     public HashCodeBuilder append(final short value) {
  765.         iTotal = iTotal * iConstant + value;
  766.         return this;
  767.     }

  768.     /**
  769.      * Append a {@code hashCode} for a {@code short} array.
  770.      *
  771.      * @param array
  772.      *            the array to add to the {@code hashCode}
  773.      * @return {@code this} instance.
  774.      */
  775.     public HashCodeBuilder append(final short[] array) {
  776.         if (array == null) {
  777.             iTotal = iTotal * iConstant;
  778.         } else {
  779.             for (final short element : array) {
  780.                 append(element);
  781.             }
  782.         }
  783.         return this;
  784.     }

  785.     /**
  786.      * Append a {@code hashCode} for an array.
  787.      *
  788.      * @param object
  789.      *            the array to add to the {@code hashCode}
  790.      */
  791.     private void appendArray(final Object object) {
  792.         // 'Switch' on type of array, to dispatch to the correct handler
  793.         // This handles multidimensional arrays
  794.         if (object instanceof long[]) {
  795.             append((long[]) object);
  796.         } else if (object instanceof int[]) {
  797.             append((int[]) object);
  798.         } else if (object instanceof short[]) {
  799.             append((short[]) object);
  800.         } else if (object instanceof char[]) {
  801.             append((char[]) object);
  802.         } else if (object instanceof byte[]) {
  803.             append((byte[]) object);
  804.         } else if (object instanceof double[]) {
  805.             append((double[]) object);
  806.         } else if (object instanceof float[]) {
  807.             append((float[]) object);
  808.         } else if (object instanceof boolean[]) {
  809.             append((boolean[]) object);
  810.         } else {
  811.             // Not an array of primitives
  812.             append((Object[]) object);
  813.         }
  814.     }

  815.     /**
  816.      * Adds the result of super.hashCode() to this builder.
  817.      *
  818.      * @param superHashCode
  819.      *            the result of calling {@code super.hashCode()}
  820.      * @return {@code this} instance.
  821.      * @since 2.0
  822.      */
  823.     public HashCodeBuilder appendSuper(final int superHashCode) {
  824.         iTotal = iTotal * iConstant + superHashCode;
  825.         return this;
  826.     }

  827.     /**
  828.      * Returns the computed {@code hashCode}.
  829.      *
  830.      * @return {@code hashCode} based on the fields appended
  831.      * @since 3.0
  832.      */
  833.     @Override
  834.     public Integer build() {
  835.         return Integer.valueOf(toHashCode());
  836.     }

  837.     /**
  838.      * Implements equals using the hash code.
  839.      *
  840.      * @since 3.13.0
  841.      */
  842.     @Override
  843.     public boolean equals(final Object obj) {
  844.         if (this == obj) {
  845.             return true;
  846.         }
  847.         if (!(obj instanceof HashCodeBuilder)) {
  848.             return false;
  849.         }
  850.         final HashCodeBuilder other = (HashCodeBuilder) obj;
  851.         return iTotal == other.iTotal;
  852.     }

  853.     /**
  854.      * The computed {@code hashCode} from toHashCode() is returned due to the likelihood
  855.      * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
  856.      * HashCodeBuilder itself is.
  857.      *
  858.      * @return {@code hashCode} based on the fields appended
  859.      * @since 2.5
  860.      */
  861.     @Override
  862.     public int hashCode() {
  863.         return toHashCode();
  864.     }

  865.     /**
  866.      * Returns the computed {@code hashCode}.
  867.      *
  868.      * @return {@code hashCode} based on the fields appended
  869.      */
  870.     public int toHashCode() {
  871.         return iTotal;
  872.     }

  873. }