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 * https://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 018package org.apache.commons.lang3.builder; 019 020import java.lang.reflect.Field; 021import java.lang.reflect.Modifier; 022import java.util.Collection; 023import java.util.Comparator; 024import java.util.HashSet; 025import java.util.Objects; 026import java.util.Set; 027 028import org.apache.commons.lang3.ArraySorter; 029import org.apache.commons.lang3.ArrayUtils; 030import org.apache.commons.lang3.ObjectUtils; 031import org.apache.commons.lang3.Validate; 032import org.apache.commons.lang3.builder.AbstractReflection.AbstractBuilder; 033 034/** 035 * Assists in implementing {@link Object#hashCode()} methods. 036 * 037 * <p> 038 * This class enables a good {@code hashCode} method to be built for any class. It follows the rules laid out in 039 * the book <a href="https://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a 040 * good {@code hashCode} method is actually quite difficult. This class aims to simplify the process. 041 * </p> 042 * 043 * <p> 044 * The following is the approach taken. When appending a data field, the current total is multiplied by the 045 * multiplier then a relevant value 046 * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then 047 * appending the integer 45 will create a hash code of 674, namely 17 * 37 + 45. 048 * </p> 049 * 050 * <p> 051 * All relevant fields from the object should be included in the {@code hashCode} method. Derived fields may be 052 * excluded. In general, any field used in the {@code equals} method must be used in the {@code hashCode} 053 * method. 054 * </p> 055 * 056 * <p> 057 * To use this class write code as follows: 058 * </p> 059 * 060 * <pre> 061 * public class Person { 062 * String name; 063 * int age; 064 * boolean smoker; 065 * ... 066 * 067 * public int hashCode() { 068 * // you pick a hard-coded, randomly chosen, non-zero, odd number 069 * // ideally different for each class 070 * return new HashCodeBuilder(17, 37). 071 * append(name). 072 * append(age). 073 * append(smoker). 074 * toHashCode(); 075 * } 076 * } 077 * </pre> 078 * 079 * <p> 080 * If required, the superclass {@code hashCode()} can be added using {@link #appendSuper}. 081 * </p> 082 * 083 * <p> 084 * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are 085 * usually private, the method, {@code reflectionHashCode}, uses {@code AccessibleObject.setAccessible} 086 * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions 087 * are set up correctly. It is also slower than testing explicitly. 088 * </p> 089 * <p> 090 * See also {@link AbstractBuilder#setForceAccessible(boolean)} 091 * </p> 092 * 093 * <p> 094 * A typical invocation for this method would look like: 095 * </p> 096 * 097 * <pre> 098 * public int hashCode() { 099 * return HashCodeBuilder.reflectionHashCode(this); 100 * } 101 * </pre> 102 * 103 * <p> 104 * The {@link HashCodeExclude} annotation can be used to exclude fields from being 105 * used by the {@code reflectionHashCode} methods. 106 * </p> 107 * 108 * @see AbstractBuilder#setForceAccessible(boolean) 109 * @since 1.0 110 */ 111public class HashCodeBuilder extends AbstractReflection implements Builder<Integer> { 112 113 /** 114 * Builds instances of CompareToBuilder. 115 */ 116 public static class Builder extends AbstractBuilder<Builder> { 117 118 private int initialOddNumber; 119 120 private int multiplierOddNumber; 121 122 /** 123 * Constructs a new Builder instance. 124 */ 125 private Builder() { 126 // empty 127 } 128 129 @Override 130 public HashCodeBuilder get() { 131 return new HashCodeBuilder(this); 132 } 133 134 135 /** 136 * Sets an odd number used as the initial value. 137 * 138 * @param initialOddNumber An odd number used as the initial value. 139 * @return {@code this} instance. 140 */ 141 public Builder setInitialOddNumber(final int initialOddNumber) { 142 this.initialOddNumber = initialOddNumber; 143 return asThis(); 144 } 145 146 /** 147 * Sets an odd number used as the multiplier. 148 * 149 * @param multiplierOddNumber An odd number used as the multiplier. 150 * @return {@code this} instance. 151 */ 152 public Builder setMultiplierOddNumber(final int multiplierOddNumber) { 153 this.multiplierOddNumber = multiplierOddNumber; 154 return asThis(); 155 } 156 157 } 158 159 /** 160 * The default initial value to use in reflection hash code building. 161 */ 162 private static final int DEFAULT_INITIAL_VALUE = 17; 163 164 /** 165 * The default multiplier value to use in reflection hash code building. 166 */ 167 private static final int DEFAULT_MULTIPLIER_VALUE = 37; 168 169 /** 170 * A registry of objects to detect cyclical object references, avoid infinite loops, and stack overflows. 171 */ 172 private static final ThreadLocal<Set<IDKey>> REGISTRY = ThreadLocal.withInitial(HashSet::new); 173 174 /** 175 * A registry of objects being appended by {@link #append(Object)}, kept separate from {@link #REGISTRY} so that 176 * guarding {@code append} against its own re-entrant cycles does not trip the reflection cycle guard checked by 177 * {@link #reflectionAppend(Object, Class, HashCodeBuilder, boolean, String[], boolean)}. 178 */ 179 private static final ThreadLocal<Set<IDKey>> APPEND_REGISTRY = ThreadLocal.withInitial(HashSet::new); 180 181 /** 182 * Registers the given object in the append registry. 183 * 184 * @param value The object to register. 185 */ 186 private static void appendRegister(final Object value) { 187 APPEND_REGISTRY.get().add(new IDKey(value)); 188 } 189 190 /* 191 * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode() 192 * we are in the process of calculating. 193 * 194 * So we generate a one-to-one mapping from the original object to a new object. 195 * 196 * Now HashSet uses equals() to determine if two elements with the same hash code really 197 * are equal, so we also need to ensure that the replacement objects are only equal 198 * if the original objects are identical. 199 * 200 * The original implementation (2.4 and before) used the System.identityHashCode() 201 * method - however this is not guaranteed to generate unique ids (e.g. LANG-459) 202 * 203 * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey) 204 * to disambiguate the duplicate ids. 205 */ 206 207 /** 208 * Unregisters the given object from the append registry. 209 * 210 * @param value The object to unregister. 211 */ 212 private static void appendUnregister(final Object value) { 213 final Set<IDKey> registry = APPEND_REGISTRY.get(); 214 registry.remove(new IDKey(value)); 215 if (registry.isEmpty()) { 216 APPEND_REGISTRY.remove(); 217 } 218 } 219 220 /** 221 * Constructs a new Builder. 222 * 223 * @return A new Builder. 224 */ 225 public static Builder builder() { 226 return new Builder(); 227 } 228 229 /** 230 * Gets the registry of objects being traversed by the reflection methods in the current thread. 231 * 232 * @return Set the registry of objects being traversed 233 */ 234 static Set<IDKey> getRegistry() { 235 return REGISTRY.get(); 236 } 237 238 /** 239 * Tests whether the append registry contains the given object. Used by {@link #append(Object)} to break its own re-entrant cycles. 240 * 241 * @param value The object to look up in the append registry. 242 * @return {@code true} if the append registry contains the given object. 243 */ 244 private static boolean isAppendRegistered(final Object value) { 245 return APPEND_REGISTRY.get().contains(new IDKey(value)); 246 } 247 248 /** 249 * Tests whether the registry contains the given object. Used by the reflection methods to avoid 250 * infinite loops. 251 * 252 * @param value 253 * The object to lookup in the registry. 254 * @return boolean {@code true} if the registry contains the given object. 255 */ 256 static boolean isRegistered(final Object value) { 257 final Set<IDKey> registry = getRegistry(); 258 return registry != null && registry.contains(new IDKey(value)); 259 } 260 261 /** 262 * Appends the fields and values defined by the given object of the given {@link Class}. 263 * 264 * @param object 265 * the object to append details of 266 * @param clazz 267 * the class to append details of 268 * @param builder 269 * the builder to append to 270 * @param useTransients 271 * whether to use transient fields 272 * @param excludeFields 273 * Collection of String field names to exclude from use in calculation of hash code 274 * @param forceAccessible Whether to set fields' accessible flags 275 */ 276 private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients, 277 final String[] excludeFields, final boolean forceAccessible) { 278 if (isRegistered(object)) { 279 return; 280 } 281 try { 282 register(object); 283 // The elements in the returned array are not sorted and are not in any particular order. 284 final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName)); 285 for (final Field field : fields) { 286 if (!ArrayUtils.contains(excludeFields, field.getName()) 287 && !field.getName().contains("$") 288 && (useTransients || !Modifier.isTransient(field.getModifiers())) 289 && !Modifier.isStatic(field.getModifiers()) 290 && !field.isAnnotationPresent(HashCodeExclude.class)) { 291 if (setAccessible(forceAccessible, field)) { 292 builder.append(Reflection.getUnchecked(field, object)); 293 } 294 } 295 } 296 } finally { 297 unregister(object); 298 } 299 } 300 301 /** 302 * Uses reflection to build a valid hash code from the fields of {@code object}. 303 * 304 * <p> 305 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 306 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 307 * also not as efficient as testing explicitly. 308 * </p> 309 * 310 * <p> 311 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 312 * {@link Object}. 313 * </p> 314 * 315 * <p> 316 * Static fields will not be tested. Superclass fields will be included. 317 * </p> 318 * 319 * <p> 320 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 321 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 322 * </p> 323 * 324 * @param initialNonZeroOddNumber 325 * a non-zero, odd number used as the initial value. This will be the returned 326 * value if no fields are found to include in the hash code 327 * @param multiplierNonZeroOddNumber 328 * a non-zero, odd number used as the multiplier 329 * @param object 330 * the Object to create a {@code hashCode} for 331 * @return int hash code 332 * @throws NullPointerException Thrown if the Object is {@code null}. 333 * @throws IllegalArgumentException Thrown if the number is zero or even. 334 * @see HashCodeExclude 335 */ 336 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) { 337 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null); 338 } 339 340 /** 341 * Uses reflection to build a valid hash code from the fields of {@code object}. 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. 356 * </p> 357 * 358 * <p> 359 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 360 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 361 * </p> 362 * 363 * @param initialNonZeroOddNumber 364 * a non-zero, odd number used as the initial value. This will be the returned 365 * value if no fields are found to include in the hash code 366 * @param multiplierNonZeroOddNumber 367 * a non-zero, odd number used as the multiplier 368 * @param object 369 * the Object to create a {@code hashCode} for 370 * @param testTransients 371 * whether to include transient fields 372 * @return int hash code 373 * @throws NullPointerException Thrown if the Object is {@code null}. 374 * @throws IllegalArgumentException Thrown if the number is zero or even. 375 * @see HashCodeExclude 376 */ 377 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object, 378 final boolean testTransients) { 379 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null); 380 } 381 382 /** 383 * Uses reflection to build a valid hash code from the fields of {@code object}. 384 * 385 * <p> 386 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 387 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 388 * also not as efficient as testing explicitly. 389 * </p> 390 * 391 * <p> 392 * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they 393 * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}. 394 * </p> 395 * 396 * <p> 397 * Static fields will not be included. Superclass fields will be included up to and including the specified 398 * superclass. A null superclass is treated as java.lang.Object. 399 * </p> 400 * 401 * <p> 402 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 403 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 404 * </p> 405 * 406 * @param <T> 407 * the type of the object involved 408 * @param initialNonZeroOddNumber 409 * a non-zero, odd number used as the initial value. This will be the returned 410 * value if no fields are found to include in the hash code 411 * @param multiplierNonZeroOddNumber 412 * a non-zero, odd number used as the multiplier 413 * @param object 414 * the Object to create a {@code hashCode} for 415 * @param testTransients 416 * whether to include transient fields 417 * @param reflectUpToClass 418 * the superclass to reflect up to (inclusive), may be {@code null} 419 * @param excludeFields 420 * array of field names to exclude from use in calculation of hash code 421 * @return int hash code 422 * @throws NullPointerException Thrown if the Object is {@code null}. 423 * @throws IllegalArgumentException Thrown if the number is zero or even. 424 * @see HashCodeExclude 425 * @since 2.0 426 */ 427 public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object, 428 final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) { 429 Objects.requireNonNull(object, "object"); 430 final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber); 431 Class<?> clazz = object.getClass(); 432 reflectionAppend(object, clazz, builder, testTransients, excludeFields, true); 433 while (clazz.getSuperclass() != null && clazz != reflectUpToClass) { 434 clazz = clazz.getSuperclass(); 435 reflectionAppend(object, clazz, builder, testTransients, excludeFields, true); 436 } 437 return builder.toHashCode(); 438 } 439 440 /** 441 * Uses reflection to build a valid hash code from the fields of {@code object}. 442 * 443 * <p> 444 * This constructor uses two hard coded choices for the constants needed to build a hash code. 445 * </p> 446 * 447 * <p> 448 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 449 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 450 * also not as efficient as testing explicitly. 451 * </p> 452 * 453 * <p> 454 * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they 455 * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}. 456 * </p> 457 * 458 * <p> 459 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 460 * in the hash code, the result of this method will be constant. 461 * </p> 462 * 463 * @param object 464 * the Object to create a {@code hashCode} for 465 * @param testTransients 466 * whether to include transient fields 467 * @return int hash code 468 * @throws NullPointerException Thrown if the object is {@code null}. 469 * @see HashCodeExclude 470 */ 471 public static int reflectionHashCode(final Object object, final boolean testTransients) { 472 return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, 473 testTransients, null); 474 } 475 476 /** 477 * Uses reflection to build a valid hash code from the fields of {@code object}. 478 * 479 * <p> 480 * This constructor uses two hard coded choices for the constants needed to build a hash code. 481 * </p> 482 * 483 * <p> 484 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 485 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 486 * also not as efficient as testing explicitly. 487 * </p> 488 * 489 * <p> 490 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 491 * {@link Object}. 492 * </p> 493 * 494 * <p> 495 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 496 * in the hash code, the result of this method will be constant. 497 * </p> 498 * 499 * @param object 500 * the Object to create a {@code hashCode} for 501 * @param excludeFields 502 * Collection of String field names to exclude from use in calculation of hash code 503 * @return int hash code 504 * @throws NullPointerException Thrown if the object is {@code null}. 505 * @see HashCodeExclude 506 */ 507 public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) { 508 return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields)); 509 } 510 511 /** 512 * Uses reflection to build a valid hash code from the fields of {@code object}. 513 * 514 * <p> 515 * This constructor uses two hard coded choices for the constants needed to build a hash code. 516 * </p> 517 * 518 * <p> 519 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 520 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 521 * also not as efficient as testing explicitly. 522 * </p> 523 * 524 * <p> 525 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 526 * {@link Object}. 527 * </p> 528 * 529 * <p> 530 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 531 * in the hash code, the result of this method will be constant. 532 * </p> 533 * 534 * @param object 535 * the Object to create a {@code hashCode} for 536 * @param excludeFields 537 * array of field names to exclude from use in calculation of hash code 538 * @return int hash code 539 * @throws NullPointerException Thrown if the object is {@code null}. 540 * @see HashCodeExclude 541 */ 542 public static int reflectionHashCode(final Object object, final String... excludeFields) { 543 return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false, 544 null, excludeFields); 545 } 546 547 /** 548 * Registers the given object. Used by the reflection methods to avoid infinite loops. 549 * 550 * @param value 551 * The object to register. 552 */ 553 private static void register(final Object value) { 554 getRegistry().add(new IDKey(value)); 555 } 556 557 /** 558 * Unregisters the given object. 559 * 560 * <p> 561 * Used by the reflection methods to avoid infinite loops. 562 * </p> 563 * 564 * @param value 565 * The object to unregister. 566 * @since 2.3 567 */ 568 private static void unregister(final Object value) { 569 final Set<IDKey> registry = getRegistry(); 570 registry.remove(new IDKey(value)); 571 if (registry.isEmpty()) { 572 REGISTRY.remove(); 573 } 574 } 575 576 /** 577 * Constant to use in building the hashCode. 578 */ 579 private final int constant; 580 581 /** 582 * Running total of the hashCode. 583 */ 584 private int total; 585 586 /** 587 * Uses two hard coded choices for the constants needed to build a {@code hashCode}. 588 */ 589 public HashCodeBuilder() { 590 this(builder().setInitialOddNumber(17).setMultiplierOddNumber(37)); 591 } 592 593 private HashCodeBuilder(final Builder builder) { 594 super(builder); 595 Validate.isTrue(builder.initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value"); 596 Validate.isTrue(builder.multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier"); 597 constant = builder.multiplierOddNumber; 598 total = builder.initialOddNumber; } 599 600 /** 601 * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class, 602 * however this is not vital. 603 * 604 * <p> 605 * Prime numbers are preferred, especially for the multiplier. 606 * </p> 607 * 608 * @param initialOddNumber 609 * an odd number used as the initial value 610 * @param multiplierOddNumber 611 * an odd number used as the multiplier 612 * @throws IllegalArgumentException Thrown if the number is even. 613 */ 614 public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) { 615 this(builder().setInitialOddNumber(initialOddNumber).setMultiplierOddNumber(multiplierOddNumber)); 616 } 617 618 /** 619 * Appends a {@code hashCode} for a {@code boolean}. 620 * 621 * <p> 622 * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}. 623 * </p> 624 * <p> 625 * This is in contrast to the standard {@link Boolean#hashCode()} handling, which computes 626 * a {@code hashCode} value of {@code 1231} for {@link Boolean} instances 627 * that represent {@code true} or {@code 1237} for {@link Boolean} instances 628 * that represent {@code false}. 629 * </p> 630 * <p> 631 * This is in accordance with the <em>Effective Java</em> design. 632 * </p> 633 * 634 * @param value 635 * the boolean to add to the {@code hashCode} 636 * @return {@code this} instance. 637 */ 638 public HashCodeBuilder append(final boolean value) { 639 total = total * constant + (value ? 0 : 1); 640 return this; 641 } 642 643 /** 644 * Appends a {@code hashCode} for a {@code boolean} array. 645 * 646 * @param array 647 * the array to add to the {@code hashCode} 648 * @return {@code this} instance. 649 */ 650 public HashCodeBuilder append(final boolean[] array) { 651 if (array == null) { 652 total = total * constant; 653 } else { 654 for (final boolean element : array) { 655 append(element); 656 } 657 } 658 return this; 659 } 660 661 /** 662 * Appends a {@code hashCode} for a {@code byte}. 663 * 664 * @param value 665 * the byte to add to the {@code hashCode} 666 * @return {@code this} instance. 667 */ 668 public HashCodeBuilder append(final byte value) { 669 total = total * constant + value; 670 return this; 671 } 672 673 /** 674 * Appends a {@code hashCode} for a {@code byte} array. 675 * 676 * @param array 677 * the array to add to the {@code hashCode} 678 * @return {@code this} instance. 679 */ 680 public HashCodeBuilder append(final byte[] array) { 681 if (array == null) { 682 total = total * constant; 683 } else { 684 for (final byte element : array) { 685 append(element); 686 } 687 } 688 return this; 689 } 690 691 /** 692 * Appends a {@code hashCode} for a {@code char}. 693 * 694 * @param value 695 * the char to add to the {@code hashCode} 696 * @return {@code this} instance. 697 */ 698 public HashCodeBuilder append(final char value) { 699 total = total * constant + value; 700 return this; 701 } 702 703 /** 704 * Appends a {@code hashCode} for a {@code char} array. 705 * 706 * @param array 707 * the array to add to the {@code hashCode} 708 * @return {@code this} instance. 709 */ 710 public HashCodeBuilder append(final char[] array) { 711 if (array == null) { 712 total = total * constant; 713 } else { 714 for (final char element : array) { 715 append(element); 716 } 717 } 718 return this; 719 } 720 721 /** 722 * Appends a {@code hashCode} for a {@code double}. 723 * 724 * @param value 725 * the double to add to the {@code hashCode} 726 * @return {@code this} instance. 727 */ 728 public HashCodeBuilder append(final double value) { 729 return append(Double.doubleToLongBits(value)); 730 } 731 732 /** 733 * Appends a {@code hashCode} for a {@code double} array. 734 * 735 * @param array 736 * the array to add to the {@code hashCode} 737 * @return {@code this} instance. 738 */ 739 public HashCodeBuilder append(final double[] array) { 740 if (array == null) { 741 total = total * constant; 742 } else { 743 for (final double element : array) { 744 append(element); 745 } 746 } 747 return this; 748 } 749 750 /** 751 * Appends a {@code hashCode} for a {@code float}. 752 * 753 * @param value 754 * the float to add to the {@code hashCode} 755 * @return {@code this} instance. 756 */ 757 public HashCodeBuilder append(final float value) { 758 total = total * constant + Float.floatToIntBits(value); 759 return this; 760 } 761 762 /** 763 * Appends a {@code hashCode} for a {@code float} array. 764 * 765 * @param array 766 * the array to add to the {@code hashCode} 767 * @return {@code this} instance. 768 */ 769 public HashCodeBuilder append(final float[] array) { 770 if (array == null) { 771 total = total * constant; 772 } else { 773 for (final float element : array) { 774 append(element); 775 } 776 } 777 return this; 778 } 779 780 /** 781 * Appends a {@code hashCode} for an {@code int}. 782 * 783 * @param value 784 * the int to add to the {@code hashCode} 785 * @return {@code this} instance. 786 */ 787 public HashCodeBuilder append(final int value) { 788 total = total * constant + value; 789 return this; 790 } 791 792 /** 793 * Appends a {@code hashCode} for an {@code int} array. 794 * 795 * @param array 796 * the array to add to the {@code hashCode} 797 * @return {@code this} instance. 798 */ 799 public HashCodeBuilder append(final int[] array) { 800 if (array == null) { 801 total = total * constant; 802 } else { 803 for (final int element : array) { 804 append(element); 805 } 806 } 807 return this; 808 } 809 810 /** 811 * Appends a {@code hashCode} for a {@code long}. 812 * 813 * @param value 814 * the long to add to the {@code hashCode} 815 * @return {@code this} instance. 816 */ 817 // NOTE: This method uses >> and not >>> as Effective Java and 818 // Long.hashCode do. Ideally we should switch to >>> at 819 // some stage. There are backwards compat issues, so 820 // that will have to wait for the time being. See LANG-342. 821 public HashCodeBuilder append(final long value) { 822 total = total * constant + (int) (value ^ value >> 32); 823 return this; 824 } 825 826 /** 827 * Appends a {@code hashCode} for a {@code long} array. 828 * 829 * @param array 830 * the array to add to the {@code hashCode} 831 * @return {@code this} instance. 832 */ 833 public HashCodeBuilder append(final long[] array) { 834 if (array == null) { 835 total = total * constant; 836 } else { 837 for (final long element : array) { 838 append(element); 839 } 840 } 841 return this; 842 } 843 844 /** 845 * Appends a {@code hashCode} for an {@link Object}. 846 * 847 * @param object 848 * the Object to add to the {@code hashCode} 849 * @return {@code this} instance. 850 */ 851 public HashCodeBuilder append(final Object object) { 852 if (object == null || isRegistered(object) || isAppendRegistered(object)) { 853 total = total * constant; 854 } else if (ObjectUtils.isArray(object)) { 855 try { 856 appendRegister(object); 857 appendArray(object); 858 } finally { 859 appendUnregister(object); 860 } 861 } else { 862 try { 863 appendRegister(object); 864 total = total * constant + object.hashCode(); 865 } finally { 866 appendUnregister(object); 867 } 868 } 869 return this; 870 } 871 872 /** 873 * Appends a {@code hashCode} for an {@link Object} array. 874 * 875 * @param array 876 * the array to add to the {@code hashCode} 877 * @return {@code this} instance. 878 */ 879 public HashCodeBuilder append(final Object[] array) { 880 if (array == null) { 881 total = total * constant; 882 } else { 883 for (final Object element : array) { 884 append(element); 885 } 886 } 887 return this; 888 } 889 890 /** 891 * Appends a {@code hashCode} for a {@code short}. 892 * 893 * @param value 894 * the short to add to the {@code hashCode} 895 * @return {@code this} instance. 896 */ 897 public HashCodeBuilder append(final short value) { 898 total = total * constant + value; 899 return this; 900 } 901 902 /** 903 * Appends a {@code hashCode} for a {@code short} array. 904 * 905 * @param array 906 * the array to add to the {@code hashCode} 907 * @return {@code this} instance. 908 */ 909 public HashCodeBuilder append(final short[] array) { 910 if (array == null) { 911 total = total * constant; 912 } else { 913 for (final short element : array) { 914 append(element); 915 } 916 } 917 return this; 918 } 919 920 /** 921 * Appends a {@code hashCode} for an array. 922 * 923 * @param object 924 * the array to add to the {@code hashCode} 925 */ 926 private void appendArray(final Object object) { 927 // 'Switch' on type of array, to dispatch to the correct handler 928 // This handles multidimensional arrays 929 if (object instanceof long[]) { 930 append((long[]) object); 931 } else if (object instanceof int[]) { 932 append((int[]) object); 933 } else if (object instanceof short[]) { 934 append((short[]) object); 935 } else if (object instanceof char[]) { 936 append((char[]) object); 937 } else if (object instanceof byte[]) { 938 append((byte[]) object); 939 } else if (object instanceof double[]) { 940 append((double[]) object); 941 } else if (object instanceof float[]) { 942 append((float[]) object); 943 } else if (object instanceof boolean[]) { 944 append((boolean[]) object); 945 } else { 946 // Not an array of primitives 947 append((Object[]) object); 948 } 949 } 950 951 /** 952 * Adds the result of super.hashCode() to this builder. 953 * 954 * @param superHashCode 955 * the result of calling {@code super.hashCode()} 956 * @return {@code this} instance. 957 * @since 2.0 958 */ 959 public HashCodeBuilder appendSuper(final int superHashCode) { 960 total = total * constant + superHashCode; 961 return this; 962 } 963 964 /** 965 * Returns the computed {@code hashCode}. 966 * 967 * @return {@code hashCode} based on the fields appended 968 * @since 3.0 969 */ 970 @Override 971 public Integer build() { 972 return Integer.valueOf(toHashCode()); 973 } 974 975 /** 976 * Implements equals using the hash code. 977 * 978 * @since 3.13.0 979 */ 980 @Override 981 public boolean equals(final Object obj) { 982 if (this == obj) { 983 return true; 984 } 985 if (!(obj instanceof HashCodeBuilder)) { 986 return false; 987 } 988 final HashCodeBuilder other = (HashCodeBuilder) obj; 989 return total == other.total; 990 } 991 992 /** 993 * Returns the computed {@code hashCode} from {@link #toHashCode()} due to the likelihood of bugs in mis-calling {@link #toHashCode()} and the unlikeliness 994 * of it mattering what the hashCode for {@link HashCodeBuilder} itself is. 995 * 996 * @return {@code hashCode} based on the fields appended 997 * @since 2.5 998 */ 999 @Override 1000 public int hashCode() { 1001 return toHashCode(); 1002 } 1003 1004 /** 1005 * Returns the computed {@code hashCode}. 1006 * 1007 * @return {@code hashCode} based on the fields appended 1008 */ 1009 public int toHashCode() { 1010 return total; 1011 } 1012 1013}