I learned that all primitives with same value have same identityHashCode so, I wanted get identityHashCode of some primitives.so when I tried with 2 doubles with same value it was giving different identityHashCode I did following:

int xInt=5;
int yInt=5;

System.out.println(System.identityHashCode(xInt));//output:1867083167
System.out.println(System.identityHashCode(yInt));//output:1867083167

double double1=5;
double double2=5;


System.out.println(System.identityHashCode(double1));//output:1915910607

System.out.println(System.identityHashCode(double2));//output:1284720968

two ints with same value have same identityHashCode but two doubles with same value have different identityHashCode why is that?

4 Answers

7
Jon Skeet On

Your code is boxing the primitive values. (The primitive values themselves don't have an identity hash code, as that's only a concept that's relevant for objects.) Your code is equivalent to this:

int xInt=5;
int yInt=5;

Integer xInteger = xInt;
Integer yInteger = yInt;

System.out.println(System.identityHashCode(xInteger));
System.out.println(System.identityHashCode(yInteger));

double double1=5;
double double2=5;

Double boxedDouble1 = double1;
Double boxedDouble2 = double2;

System.out.println(System.identityHashCode(boxedDouble1));
System.out.println(System.identityHashCode(boxedDouble2));

Now if you compare the references themselves, you'll see that xInteger == yInteger is true, but boxedDouble1 == boxedDouble2 is false... so identityHashCode is representing that relationship accurately.

The reason your boxed integer references refer to the same object is that boxed integral types within a particular range are cached:

If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.

The range can actually be bigger in practice, and an implementation could cache boxed doubles as well, but I haven't seen that happen.

0
JB Nizet On

i learned that all primitives with same value have same identityHashCode

That can't be true, since primitives, by definition, are not objects, and thus don't have an identity hash code in the first place.

When you're calling System.identityHashCode(), the argument is boxed to an Integer or a Double.

And Integer boxing uses a cache for the frequently used integers (from -128 to 127 by default). That's not the case for Double boxing.

Try it with a large int, and you'll get different results, too.

0
achAmháin On

There's a boxing issue at play here - you can't compare primitive datatypes with identityHashCode as it uses Object as its parameter.

Returns the same hash code for the given object as would be returned by the default method hashCode()

But of course double isn't the same as Double.

0
John Bollinger On

i learned that all primitives with same value have same identityHashCode.

There are at least two misconceptions there. First, primitives don't have hash codes or identity hash codes at all. It is Objects that do, such as the wrapper objects obtained by autoboxing primitive values.

Second, the overall idea is simply wrong, as your own experiment demonstrates. If you provide a primitive as the argument to System.identityHashCode() then it is autoboxed into an instance of the appropriate wrapper class, and the identity hash code of the resulting object is returned. An object's identity hash code is uniquely characteristic of that object during its lifetime, and independent of its state. No two objects existing at the same time have the same identity hash code. What's more interesting, then, is not that you get different identity hash codes for the autoboxed doubles, but that you get the same identity hash codes for autoboxed small integers.

In fact, this shows that Java maintains a cache of Integer objects for small integer values. It uses these when autoboxing values in the range covered, and when handling explicit Integer.valueOf() invocations for those values. Thus, in your example, you get the same object each time you autobox the integer 5, and you see the same identity hash code. If you used a sufficiently large value then you would not see the same effect.

Java does not perform such caching for the Doubles with value 5.0.

On the other hand, perhaps you simply misunderstood the lesson. Distinct wrapper objects representing the same primitive type and value don't have the same identity hash code, but they do have the same (regular) hash code, because that, for the wrapper classes, is determined by the primitive values they represent. So compare the results of your code to the results of this:

    System.out.println(Double.valueOf(double1).hashCode());
    System.out.println(Double.valueOf(double2).hashCode());