3

I was just writing code, and suddenly I came across this warning in Netbeans:

hashCode() called on array instance

It occurred in this piece of code:

public class SomeObject {

    private String a;
    private char[] b;

    @Override
    public boolean equals(Object anotherObject) {
        if (!(anotherObject instanceof SomeObject)) {
            return false;
        }
        SomeObject object = (SomeObject) anotherObject;
        return (this.a.equals(object.a) && arraysAreEqual(this.b, object.b));
    }

    // When I created the equals() method, Netbeans warned me:
    // 'Generate missing hashCode()'. Okay then, here it comes:

    @Override
    public int hashCode() {
        return (43 * this.a.hashCode() + 11 * this.b.hashCode()); // MARKED LINE.
    }
}

The warning occurs on the marked line. The IDE finds that I should avoid calling hashCode() on an array instance.

Now why should I avoid using hashCode() on an array?

Notice that I read this question and answer, but they didn't mention this.

3
  • If memory serves, arrays inherit the default hashCode() implementation, so perhaps that is why. Commented Jun 24, 2014 at 11:36
  • see stackoverflow.com/questions/744735/… Commented Jun 24, 2014 at 11:38
  • Riiight. That makes sense. Seems this question has its duplicate. Commented Jun 24, 2014 at 13:15

4 Answers 4

3

Java arrays are directly derived from java.lang.Object and thus inherit the methods equals and hashCode from it.

The default equals method compares object identity (i.e. whether two references refer to the same object), and the default hashCode method will most probably return different values for different objects.

In most cases, this is a behavior that you do not want. You most probably want to compare arrays based on the content. Note, that your equals method seems to do that, which in turn means that your hashCode method is broken. Look at the method's documentation for the reason.

Java provides a class with helper methods for exactly that reason: java.util.Arrays. It provides the methods equals and hashCode that are both based on the content of the array.

So you should write it like that:

public class SomeObject {

    private String a;
    private char[] b;

    @Override
    public boolean equals(Object anotherObject) {
        if (!(anotherObject instanceof SomeObject)) {
            return false;
        }
        SomeObject object = (SomeObject) anotherObject;
        return (this.a.equals(object.a) && Arrays.equals(this.b, object.b));
    }

    @Override
    public int hashCode() {
        return (43 * this.a.hashCode() + 11 * Arrays.hashCode(this.b));
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

I would better use:

java.utils.Arrays.hashCode(char[] a)

http://www.tutorialspoint.com/java/util/arrays_hashcode_char.htm

In your way you're not testing the contents of the char array.

The java.util.Arrays.hashCode(char[]) method returns a hash code based on the contents of the specified array. For any two char arrays a and b such that Arrays.equals(a, b), it is also the case that Arrays.hashCode(a) == Arrays.hashCode(b).

public void testHashCode() {

    char[] b = { 'a', 'b' };
    char[] a = { 'a', 'b' };
    System.out.println("HashCode b:" + b.hashCode() + " a:" + a.hashCode());
    System.out.println("Array hashCode a:" + java.util.Arrays.hashCode(a) + " b:" + java.util.Arrays.hashCode(b));
}

Result:

HashCode b:8995841 a:8995844
Array hashCode a:4066 b:4066

Hope this helps!

4 Comments

Er, isn't toString() for arrays inherited from Object? So that would be basically as useless as plain hashCode()?
you're right. best option is first one. added a test
Perhaps you should suggest something more useful than toString() if you are going to include an alternative?
Completely agreee. I changed my answer.
0

The problem is that you can't override an array and it is using the default hashCode() implementation which can cause problems. You can consider this as a design oversight. You should either wrap your arrays in an arbitrary object or don't use hashCode() altogether in the context of arrays.

Comments

0

The hashCode implementation for arrays is based on the identity of the array and not on the content. In most cases, this is not what you want, since two arrays with identical content will in general have different hash codes.

To base the hash code on the contents of the array you can use the java.utils.Arrays.hashCode method.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.