9

When should I use the System.identityHashCode() and hashcode() methods?

Michael Mior
  • 28,107
  • 9
  • 89
  • 113
Srinivas
  • 99
  • 1
  • 2
  • 1
    possible duplicate of [How do hashCode() and identityHashCode() work at the back end?](http://stackoverflow.com/questions/4930781/how-do-hashcode-and-identityhashcode-work-at-the-back-end) – Rüdiger Herrmann Jul 23 '15 at 06:36

5 Answers5

4

According to the javadoc, the System.identityHashCode(Object o):

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

So, at the first place, System.identityHashCode(nullReference) will always give you 0, instead of nullReference.hashCode() which will obviously give you a NullPointerException at Runtime.

Let's, however, consider the following class:

public class MysteriousOne {
    @Override
    public int hashCode() {
        return 0xAAAABBBB;
    }

    //override equals() and so on...
}

The class overrides hashCode(), which is perfectly fine, even though the hash code for every instance would be the same, which however is not fine, if you want to distinguish identities of several instances. Usually, you'd try the output of the .toString() method (which by default gives the classname, followed by a @ followed by the hashCode() output), for example, to find out the real identity of an object, but is in this case the output would be the same:

MysteriousOne first = new MysteriousOne();
MysteriousOne second = new MysteriousOne();
System.out.println("First: " + first);
System.out.println("Second: " + second);

The output would be:

First: MysteriousOne@aaaabbbb
Second: MysteriousOne@aaaabbbb

So, having such implementation of hashCode() is impossible to distinguish between identities of several instances. Which is where System.identityHashCode() is being handy.

If you do

System.out.println("First: " + System.identityHashCode(first));
System.out.println("Second: " + System.identityHashCode(second));

you'd get two different numbers for the different instances, even though the hashCode() of their class implementation returns a constant (actually here the overridden implementation of hashCode() will not be called at all, as per javadoc):

First: 366712642
Second: 1829164700

Further, you can even pass primitives to System.identityHashCode(Object o), as they will be boxed to their corresponding wrappers:

int i = 5;
System.out.println(System.identityHashCode(i));

More info:

Community
  • 1
  • 1
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • I don't really agree with this answer, instead of using `identityHashCode` the author of that `hashCode()` should have fixed that function instead :) , having the same constant `hashCode` for every object instance seems an improper implementation of the method. This does not seem a good use case for `identityHashCode`. – uraimo Jul 23 '15 at 07:31
  • 3
    It was just a sample to point out that with calling `System.identityHashCode()`, the overriden `hashCode()` implementation will not be taken in place. – Konstantin Yovkov Jul 23 '15 at 07:37
0

Some of your classes may override hashcode() method in your system. For those objects, this method provides the hash code of the provided Object as would be returned from its ultimate parent java.lang.Object. Refer Java API to see the description from language designers.

I believe the use is when you want to create almost non-unique objects for some reasons. When I say almost, there may be objects with same hash code. You would actually minimize the use of equals methods in doing so.

sakthisundar
  • 3,278
  • 3
  • 16
  • 29
0

From the documentation:

public static int identityHashCode(Object x)

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

Note that identityHashCode returns the hashCode as implemented in the Object class and that's not what you usually want, so you should just use yourObject.hashCode().

Regarding if there could be some use cases for this method, if you have an array of Objects you are iterating through that could have some null in it, and you need the hashCode of those Objects, using System.identityHashCode(obj) could save you one null check, not that big of an improvement.

Community
  • 1
  • 1
uraimo
  • 19,081
  • 8
  • 48
  • 55
0

The System.identityhashcode() always return the default java.lang.Object implementation, even if the class for a particular object overrides this and computes a different hash code.

Under some circumstance, you may need this kind of definition: Two objects o1 and o2 are considered equal if and only if o1 == o2. In normal implementations, two objects o1 and o2 are considered equal if and only if o1 == null ? o2 == null : o1.equals(o2). If two objects are equal if and only if o1 == o2, they must have the same hashcode. So you should use System.identityhashcode().

Here are some code snippets I came across.


private static int hash(Object x, int length) {
    int h = System.identityHashCode(x);
    // Multiply by -127, and left-shift to use least bit as part of hash
    return ((h << 1) - (h << 8)) & (length - 1);
}

IdentityHashMap.java

public int hashCode() {
    return System.identityHashCode(instance);
}

@Override
@SuppressWarnings("rawtypes")
public boolean equals(final Object other) {
    return other instanceof IdentityWrapper &&
         ((IdentityWrapper) other).instance == instance;
}

IdentityWrapper.java (From Apache Commons Pool 2)

sofia
  • 763
  • 8
  • 11
-2

Well, for starters, while System of course has a hashCode() method (every Object has one), I don't see much reason in calling it. Or any chance of even getting a System object to call it on, as System is final and the constructor is private. So, probably "pretty much never" for hashCode(), I guess.

So, that leaves us with System.identityHashCode(Object) which gives your simply the default hashcode value for any Object. So, in other words, you don't need it very often, because if you don't override the hashCode() method in your class, you will already get the same return value by default for your Objects (because effectively the default hashCode(), when you have not overriden the hashCode() method, is simply System.identityHashCode(this)). There might be some use cases when to use it, but they are pretty rare.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58