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