diff --git a/src/main/java/org/apache/commons/lang3/ObjectUtils.java b/src/main/java/org/apache/commons/lang3/ObjectUtils.java index 89c04fa73..6d4017085 100644 --- a/src/main/java/org/apache/commons/lang3/ObjectUtils.java +++ b/src/main/java/org/apache/commons/lang3/ObjectUtils.java @@ -189,9 +189,41 @@ public class ObjectUtils { * @since 2.1 */ public static int hashCode(Object obj) { + // hashCode(Object) retained for performance, as hash code is often critical return (obj == null) ? 0 : obj.hashCode(); } + /** + *

Gets the hash code for multiple objects.

+ * + *

This allows a hash code to be rapidly calculated for a number of objects. + * The hash code for a single object is the not same as {@link #hashCode(Object)}. + * The hash code for multiple objects is the same as that calculated by an + * {@code ArrayList} containing the specified objects.

+ * + *
+     * ObjectUtils.hashCodeMulti()                 = 1
+     * ObjectUtils.hashCodeMulti((Object[]) null)  = 1
+     * ObjectUtils.hashCodeMulti(a)                = 31 + a.hashCode()
+     * ObjectUtils.hashCodeMulti(a,b)              = (31 + a.hashCode()) * 31 + b.hashCode()
+     * ObjectUtils.hashCodeMulti(a,b,c)            = ((31 + a.hashCode()) * 31 + b.hashCode()) * 31 + c.hashCode()
+     * 
+ * + * @param first the first object, may be {@code null} + * @param objects the objects to obtain the hash code of, may be {@code null} + * @return the hash code of the objects, or zero if null + * @since 3.0 + */ + public static int hashCodeMulti(Object... objects) { + int hash = 1; + if (objects != null) { + for (int i = 0; i < objects.length; i++) { + hash = hash * 31 + ObjectUtils.hashCode(objects[i]); + } + } + return hash; + } + // Identity ToString //----------------------------------------------------------------------- /** diff --git a/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java b/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java index b4a1bca59..0b473f413 100644 --- a/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java @@ -18,9 +18,11 @@ package org.apache.commons.lang3; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.List; import junit.framework.TestCase; @@ -97,6 +99,30 @@ public class ObjectUtilsTest extends TestCase { assertEquals("a".hashCode(), ObjectUtils.hashCode("a")); } + public void testHashCodeMulti_multiple_emptyArray() { + Object[] array = new Object[0]; + assertEquals(1, ObjectUtils.hashCodeMulti(array)); + } + + public void testHashCodeMulti_multiple_nullArray() { + Object[] array = null; + assertEquals(1, ObjectUtils.hashCodeMulti(array)); + } + + public void testHashCodeMulti_multiple_likeList() { + List list0 = new ArrayList(Arrays.asList()); + assertEquals(list0.hashCode(), ObjectUtils.hashCodeMulti()); + + List list1 = new ArrayList(Arrays.asList("a")); + assertEquals(list1.hashCode(), ObjectUtils.hashCodeMulti("a")); + + List list2 = new ArrayList(Arrays.asList("a", "b")); + assertEquals(list2.hashCode(), ObjectUtils.hashCodeMulti("a", "b")); + + List list3 = new ArrayList(Arrays.asList("a", "b", "c")); + assertEquals(list3.hashCode(), ObjectUtils.hashCodeMulti("a", "b", "c")); + } + // /** // * Show that java.util.Date and java.sql.Timestamp are apples and oranges. // * Prompted by an email discussion.