I am using Java 7, and I have the following class below. I implemented equals
and hashCode
correctly, but the problem is that equals
r
HashCode being 32 bit int value, there is always a possibility of collisions(same hash code for two objects), but its rare/coincidental. Your example is one of the such a highly coincidental one. Here is the explanation.
When you call Objects.hash
, it internally calls Arrays.hashCode()
with logic as below:
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
For your 3 param hashCode, it results into below:
31 * (31 * (31 *1 +hashOfString1)+hashOfString2) + hashOfString3
For your first object. Hash value of individual Strings are:
chamorro --> 1140493257 english --> 1698758127 notes --> 0
And for second object:
chamorro --> 1140494218 english --> 1698728336 notes -->0
If you notice, first two values of the hash code in both objects are different.
But when it computes the final hash code as:
int hashCode1 = 31*(31*(31+1140493257) + 1698758127)+0;
int hashCode2 = 31*(31*(31+1140494218) + 1698728336)+0;
Coincidentally it results into same hash code 1919283673
because int
is stored in 32 bits.
Verify the theory your self be using the code segment below:
public static void main(String... args) {
ChamorroEntry entry1 = new ChamorroEntry("Åguigan",
"Second island south of Saipan. Åguihan.", "");
ChamorroEntry entry2 = new ChamorroEntry("Åguihan",
"Second island south of Saipan. Åguigan.", "");
System.out.println(entry1.equals(entry2)); // returns false
System.out.println("Åguigan".hashCode());
System.out.println("Åguihan".hashCode());
System.out.println("Second island south of Saipan. Åguihan.".hashCode());
System.out.println("Second island south of Saipan. Åguigan.".hashCode());
System.out.println("".hashCode());
System.out.println("".hashCode());
int hashCode1 = 31*(31*(31+1140493257) + 1698758127)+0;
int hashCode2 = 31*(31*(31+1140494218) + 1698728336)+0;
System.out.println(entry1.hashCode() + "\n" + entry2.hashCode());
System.out.println(getHashCode(
new String[]{entry1.chamorro, entry1.english, entry1.notes})
+ "\n" + getHashCode(
new String[]{entry2.chamorro, entry2.english, entry2.notes}));
System.out.println(hashCode1 + "\n" + hashCode2); // returns same hash code!
}
public static int getHashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
If you use some different string parameters, hope it will result into different hashCode.