why two primitive doubles with same value have two different identityHashCode? - java

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?

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.

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.

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.

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());

Related

Default data type of the constants printed in System.out.print();

System.out.println(2147483647 + 1); //prints -2147483648
I know 2147483647 is the max value of integer data type. My question is why is this result calculated for Integer type, and why was it not considered for Long or double?
Because...
System.out.println(127+1); //prints 128
here why is 127 not considered for Byte data type, resulting in the result to be -128?
Fundmentally, you seem to not fully understand literals. A number without a decimal point or suffix is always an int, regardless of it's magnitude. This can be further complicated by implicit widening when assigning to larger primitive datatypes (e.g. int may be implicitly widened to long).
So now we know that your two literals are ints. int + int is always int. It doesn't matter whether the result will overflow or not.
If you know or suspect that the constants will exceed the range of int, add the suffix L (i.e. 2147483647L and 1L) to explicitly declare that these are longs. long + long = long, so the result will not overflow in this case.
println is overloaded with several inputs, your paramters are of type int so method will be called
public void print(int i) {
write(String.valueOf(i));
}
Every number in java sorce code is by default an integer. If you like to have an other type like long, you need to extend your number with an 'L' (e.g. 23409L) or you have to cast it. Only at initialization from a variable the compiler make the cast for you.
In many cases you can give byte or short also to methodes, even if they request for an integer parameter. But this only works because of java's conversions and promotions mechanism.
Because of all this functionalities some programmer mess up with the real data types they have at one point of the code.
For more infos visit the oracle documentation:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html

Why same values got from ArrayList are changed to different ones?

I am using Java ArrayList.
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(-129);
list.add(-129);
return (list.get(0) == list.get(1));
The return value is false.
I know it must be some range problem since when I use -128, it returns true.
But could someone tell me the reason of it?
Java caches integers in the range -128..127 (signed bytes). It saves a lot of allocations of tiny numbers which is very common in lots of code. If you use equals() instead of ==, it will work. The == check is comparing that two int types, that have been magically boxed (i.e. converted) to Integer are the same reference - which they are not. But int in the signed byte range will be the same. The equals check will actually compare the value of the variables:
return (list.get(0).equals(list.get(1)));
When you perform:
list.add(-129);
list.add(-129);
It create two separate object with separate memory location.when you perform == it return false.
In Java, values from -128 to 127 are cached, so the same objects are returned and you will get true.
For more information see:http://www.geeksforgeeks.org/comparison-autoboxed-integer-objects-java/
If two references point to two different objects, then in accordance with the "= =" to judge both is unequal, even though both have the same reference content. As we know, if two references refer to the same object, in accordance with the "= =" to judge the two are equal.
If you go to the Integer. Java classes, you will find that there is a internal private class IntegerCache. Java, it caches from all the Integer object - between 128 ~ 127.
So the thing is, all the small integers are in the internal cache.
If the value is between 128 ~ 127, then it will be returned from a cache instance,point to the same object.

vectors in java contains only objects?

I have this question,
vectors in java only accept objects right? but this piece of code compiles just fine
Vector myv=new Vector();
myv.addElement(1);
myv.addElement(1);
does it encapsulate it as an object of Integer? and if it does, why do this statement
System.out.println(myv.elementAt(0)==myv.elementAt(1));
gives true ?!!! they're supposed to be two distinct objects...?
at the same time this statement throws an error, which ensures that the element is an object.
int x=myv.elementAt(0);
can someone explain this for me? thank you.
The 1 is auto-boxed into an Integer.
To learn more about Autoboxing and -unboxing, see Oracle's Docu: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
On why they are the same: Autoboxing ints to Integers uses a cache. For numbers < 128 (I think) the same Integer-Object will be returned each time instead of a new one being created. So your code essentially inserts the same object twice into the Vector, and for this reason the identity comparison using == returns true.
As you don't use generics with your Vector, myv.elementAt(0) will return an Object, which cannot be cast to an int. If you used generics, i.e. Vector<Integer> myv = new Vector<>(), then elementAt would return an Integer which would be auto-unboxed to an int.
That works because java auto boxes and auto unboxes these type for you.
But note that this doesn't work for sure in every scenario.
Let's take this example:
Integer i = 1234;
Integer z = 1234;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
It will produce the following output:
i: 1234
z: 1234
== : false
equals: true
DEMO
In fact, from this answer you can see that it works only for integers between -128 and +127
In fact, this behaves as expected:
Integer i = 123;
Integer z = 123;
System.out.println("i: "+i);
System.out.println("z: "+z);
System.out.println("== : "+(i == z));
System.out.println("equals: "+i.equals(z));
and produces:
i: 123
z: 123
== : true
equals: true
DEMO
Here is something pretty funny about Java, it caches integers between -128 and 127 (for auto-/un-boxing) and any reference to integers in that range all refer to the same object (since == here is comparing Objects). This can cause quite a few bugs when people don't thing through the == method comparing Objects, rather than values.
So you will get true for comparing "integers" (autoboxed) between -128 - 127. If you do the same thing with 128, it'll say false.
Check it out:
import java.util.Vector;
public class Vect {
public static void main(String[] args) {
Vector v = new Vector();
v.addElement(127);
v.addElement(127);
v.addElement(128);
v.addElement(128);
System.out.println(v.elementAt(0) == v.elementAt(1));
System.out.println(v.elementAt(2) == v.elementAt(3));
}
}
Will give you:
$ java Vect
true
false
This is called autoboxing. When the Java compiler encounters an integer, float or double value in a place where an object is expected, it automatically creates a wrapper object.
The code generated by the compiler for your code is equivalent to
Vector myv=new Vector();
myv.addElement(Integer.valueOf(1));
myv.addElement(Integer.valueOf(1));
The valueOf() method caches Integer instances for the values from -128 to 127 (IIRC), with the result that both values will be replaced by the same object.
Try the same with a lager value, like 1000. Then the objects will be different.
This is a feature of compiled code and auto-boxing.
Generics in Java are a compile-time issue. javac uses them to check that you use the types correctly, but the compiled byte code that's produced doesn't know anything about the generic types. Generics are implemented with type erasure in Java was mainly for backward compatibility. (That's also why raw types still exist in Java.)
It means that an Vector<E> will look like a plain, raw Vector at runtime - it's just a plain Vector that contains objects. Since primitives are not objects, you can't store primitive types in such an Vector.
There are wrapper classes for each of the primitive types (int -> Integer, long -> Long, short -> Short, boolean --> Boolean, etc.) so is possible to make it such that a Vector<int> would use auto-boxing to store ints in Integer objects, which could be stored in a Vector. ...but the designers of the Java language didn't decide to take auto-boxing that far.
Java's Vector is a generics, it means it can accept any kind of data to store. You have to specify the type of data to hold with a syntax like Vector<String>. Replace String for the kind of object you want the Vector to hold.
The reason that it gives true is because it is autoboxed into the Integer class automatically; when compares two Integers, it does the same way as the built-in type int.
EDIT: The autoboxing comparation works with the int values in the range [-128;+127].

why does new Integer(i).hashCode() return i?

I want to know why new Integer(i).hashCode() or new Long(i).hashCode() returns i but when hashCode() is invoked by some other object say new Double(345).hashCode(), it returns a random number. Why?
Because the int value of an Integer perfectly satisfies and fully complies with the general contract of Object.hashCode():
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
In short:
The hash codes for 2 objects must be the same if equals() returns true and should be (but not required) different if equals() returns false. Also by the declaration of Object.hashCode() it must be an int. Ideally the hash code should depend on all the data that is hashed.
Hash code of Long
Long has to map 8 bytes to 4 bytes (size of an int). Current implementation of Long.hashCode() will only return i if it fits into an int, else it will be XOR'ed with the upper 32 bits (4 bytes):
return (int)(value ^ (value >>> 32));
Hash code of Double
Obviously the double value of a Double does not qualify for this. Double also has to map 8 bytes to 4 bytes.
Double.hashCode() will return a seemingly random value because floating point numbers (float and double) are not stored "nicely" (e.g. 2's complement like int or long) in the bytes that are reserved for them but using IEEE 754 binary floating point standard and so mapping those 8 bytes to 4 (this is exactly what the implementation does) will not be a meaningful number as an int which uses 2's complement representation.
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
A value of an integer is a good enough hash because it is just as unique as the unique integer number itself.
A double has to be hashed in some different manner because the hash here has to be an integer.
Becase the implementation say it:
Returns a hash code for this Integer.
Returns:a hash code value for this object, equal to the primitive int value represented by this Integer object.
707
708 public int hashCode() {
709 return value;
710 }
Different types in Java compute hash codes in different ways, non of them is random. In the case of Long Integer and Double the hashcode is the value except in the case of Double where it is converted to int
This is because hashcode() method of Integer class returns value as hashcode.
Returns a hash code for this <code>Integer</code>.
#return a hash code value for this object, equal to the
primitive <code>int</code> value represented by this
<code>Integer</code> object.
public int hashCode() {
return value;
}
While hashcode() method of Double class performs some operation and returns hashcode.
Returns a hash code for this Double object. The result is the exclusive OR
of the two halves of the long integer bit representation, exactly as produced by
the method {#link #doubleToLongBits(double)}, of the primitive double value
represented by this Double object. That is, the hash code is the value of the
expression:
public int hashCode() {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
The Integer class "boxes" a primitive int value, but it has an object reference of its own. If Object.equals() states that two equal objects A and B must both exhibit the same Object.hashCode(), it makes sense that such hash code be the former int value.
As for Double, its value might change between systems, which is why it makes sense to rely on a different mechanism to provide a hash code.

Weird equality behavior in java [duplicate]

This question already has answers here:
Weird Integer boxing in Java
(12 answers)
Closed 8 years ago.
Take a look at following code:
Long minima = -9223372036854775808L;
Long anotherminima = -9223372036854775808L;
System.out.println(minima==anotherminima); //evaluates to false
System.out.println(Long.MIN_VALUE);
Long another= 1L;
Long one = 1L;
System.out.println(another == one); //evaluates to true
I am not able to understand this behavior..? I was hoping the first eval to be true as well..
And that is what I am expecting..
There is a caching technique used by the JVM for some range of autoboxing value. As specified in the spec ( http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 )
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an identical reference. In practice, this may not be feasible using existing implementation techniques. The rules above are a pragmatic compromise. The final clause above requires that certain common values always be boxed into indistinguishable objects. The implementation may cache these, lazily or eagerly. For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
This ensures that in most common cases, the behavior will be the desired one, without imposing an undue performance penalty, especially on small devices. Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.
So 1L is in this cached values and then the autoboxing give the exact same reference, but in the case of the number outside of this range (like the Long.MIN_VALUE) it isn'T cached and thus a different instance/reference is given.
In any case, when comparing object you should always use .equals()
Just a guess here, but it could be that 1L is in the constant pool, and thus the reference equality evaluates to true (just like how sometimes, even by Strings, == will evaluate to true), while that other huge number isn't. Not sure how to check which constants are in the pool at initiation.
Edit: Java has a cache of certain constant objects (including the wrapper classes for primitives, and String). Thus, if you write
String st1 = "A";
if "A" is in the constant pool, Java won't create a new String object- it will just create a reference to the already existing one. So if you then did
String st2 = "A";
System.out.println(st1 == st2);
It would print out true.
Now, not all Integer, Long, Short, etc... are cached (there are way too many), but the lower values are. So I would assume that 1L is. That means that in your question, both another and one refer to the same object, and thus it returns true even for reference equality.
First of all you should use long instead of Long. Secondly == between Integer, Long etc will check for reference equality. You may check the 5.1.7 Boxing Conversion. Alo 1L is in the constant pool so the second case is returning true.
On a side note you should use .equals for comparing the long.
From the Oracle docs:
If the value p being boxed is true, false, a byte, or a char in the
range \u0000 to \u007f, or an int or short number between -128 and 127
(inclusive), then let r1 and r2 be the results of any two boxing
conversions of p. It is always the case that r1 == r2.
Ideally, boxing a given primitive value p, would always yield an
identical reference. In practice, this may not be feasible using
existing implementation techniques. The rules above are a pragmatic
compromise. The final clause above requires that certain common values
always be boxed into indistinguishable objects. [...]
This ensures that in most common cases, the behavior will be the
desired one, without imposing an undue performance penalty, especially
on small devices. Less memory-limited implementations might, for
example, cache all char and short values, as well as int and long
values in the range of -32K to +32K.
Adding on to this answer, everything from -128 to 127 is cached into an instance in permanent java memory, meaning that those numbers (almost) always have reference equality, because new instances are not created for them. Outside of the cache, a new instance is created every time the number is used, so they are not equal referentially. Read more here and here
problem:
(minima==anotherminima)
You are comparing the memory location of the object not its values thus it returns false.
If you want to compare two long wrapper class you need to call compareTo
From jls
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f,
or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results
of any two boxing conversions of p. It is always the case that r1 == r2.
Now if you use -128 and 127 to initialized the Long wrapper class it will result to boxing conversion which will have the same reference.
You should use long instead of Long. Note that Long is a class and so you must use equals() to compare instances of it. On the other hand, if you use long instead, you can compare with == because these are primitives.

Categories