object identityhashcode in java - java

I've been working in my project (I'm also using EMF Compare). I need to keep an unique ID for each object that I'm using, that's why I decided to use the IdentityHashCode, as far as I understand, this value is the same through the compilation.
I have given the object as a parameter in the method of another class, but when I try to get the hashcode this is not the same that I can see when I print the value of the object.
Something like this:
System.out.println("The Object is: "+obj)
System.out.println("The hash ID is: +Integer.toHexString(System.identityHashCode(obj)));
But as a result I get this:
The Object is : ***xxxxxxxxxxxxxx***.EntityImpl#18e588c (name: Comment) has been removed.
The hash ID is: 1ec1758
As you can see the two values (18e588c and 1ec1758) are totally different, but I can't understand why. Until now the only thing that I have done (and it works) is to get the String of the object and then use the substring method to get 18e588c (for this example)
I'd appreciate any answer.

I need to keep an unique ID for each object that I'm using, that's why I decided to use the IdentityHashCode, as far as I understand, this value is the same through the compilation.
No. It's got nothing to do with compilation, and it's not guaranteed to be unique.
It's not clear what you're trying to do, but you simply shouldn't regard hash codes as unique - they're not guaranteed to be.
The Object.hashCode documentation specifies:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
That's not the same thing as guaranteeing it though.
You're also being confused by the result of calling toString() - I suspect your class actually overrides hashCode(), and Object.toString() calls the potentially-overridden hashCode() method rather than using the identity hash code:
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
If you call obj.hashCode() you'll see the same value that's shown by toString.

Related

If the hashcode() creates hashcode based on the address of the object, how can two different objects with same contents create the same hashcode?

When you read the description of hashCode() in the Object class, it says that
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.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
It does not happen with String class's hashcode() because the String class's hashcode() creates integer value based on the content of the object. The same content always creates the same hash value.
However, it happens if the hash value of the object is calculated based on its address in the memory. And the author of the article says that the Object class calculates the hash value of the object based on its address in the memory.
In the example below, the objects, p1 and p2 have the same content so equals() on them returns true.
However, how come these two objects return the same hash value when their memory addresses are different?
Here is the example code: main()
Person p1 = new Person2("David", 10);
Person p2 = new Person2("David", 10);
boolean b = p1.equals(p2);
int hashCode1 = p1.hashCode();
int hashCode2 = p2.hashCode();
Here is the overriden hashcode()
public int hashCode(){
return Objects.hash(name, age);
}
Is the article's content wrong?
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
I think you have misunderstood this statement:
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.
The word “must” means that you, the programmer, are required to write a hashCode() method which always produces the same hashCode value for two objects which are equal to each other according to their equals(Object) method.
If you don’t, you have written a broken object that will not work with any class that uses hash codes, particularly unsorted Sets and Maps.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
Yes, hashCode() can provide different values in different runtimes, for a class which does not override the hashCode() method.
… how come these two objects return the same hash value when their memory addresses are different?
Because you told them to. You overrode the hashCode() method.
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
It doesn’t have a lot of use. That’s why programmers are strongly recommended to override the method, unless they don’t care about object identity.
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
No it does not. The contract states:
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.
As long as the hashCode method defined in the Object class returns the same value for the duration of the Java runtime, it is compliant.
The contract also says:
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.
Two objects whose equals method reports that they are effectively equal must return the same hashCode. Any instance of the Object class whose type is not a subclass of Object is only equal to itself and cannot be equal to any other object, so any value it returns is valid, as long as it is consistent throughout the life of the Java runtime.
The article is wrong, memory address is not involved (btw. the address can change during the lifecycle of objects, so it's abstracted away as a reference). You can look at the default hashCode as a method that returns a random integer, which is always the same for the same object.
Default equals (inherited from Object) works exactly like ==. Since there is a condition (required for classes like HashSet etc. to work) that states when a.equals(b) then a.hashCode == b.hashCode, then we need a default hashCode which only has to have one property: when we call it twice, it must return the same number.
The default hashCode exists exactly so that the condition you mention is upheld. The value returned is not important, it's only important that it never changes.
No p1 and p2 does not have the same content
If you do p1.equals(p2) that will be false, so not the same content.
If you want p1 and p2 to equal, you need to implement the equals methods from object, in a way that compare their content. And IF you implement the equals method, then you also MUST implement the hashCode method, so that if equals return true, then the objects have the same hashCode().
Here's the design decision every programmer needs to make for objects they define of (say) MyClass:
Do you want it to be possible for two different objects to be "equal"?
If you do, then firstly you have to implement MyClass.equals() so that it gives the correct notion of equality for your purposes. That's entirely in your hands.
Then you're supposed to implement hashCode such that, if A.equals(B), then A.hashCode() == B.hashCode(). You explicitly do not want to use Object.hashCode().
If you don't want different objects to ever be equal, then don't implement equals() or hashCode(), use the implementations that Object gives you. For Object A and Object B (different Objects, and not subclasses of Object), then it is never the case that A.equals(B), and so it's perfectly ok that A.hashCode() is never the same as B.hashCode().

Wrapper class strange behaviour in java

public class Test {
public static void main(String args[]) {
int i = 10;
Integer a = new Integer(i);
System.out.println(a); //tostring method overriden
System.out.println(a.hashCode());
}
}
Output:
10
10
now my question is why hashCode() method is overriden in this case.
If I want to find the object reference of the wrapper class object a in the above code.
How do i do it?
The object reference to the integer in your case is a. Unlike C, in Java, you can't get a reference pointer to an object. The hashCode is not used to identify the address location of an object in the memory.
From the hashCode API,
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.
As it turns out, the most efficient value of hashCode for an integer is the value itself.
If you still want to get hold of the original hash value of the object, I would suggest using the System.identityHashCode method.
System.identityHashCode(a)
my question is why hashCode method is overriden in this case
Wrappers, like String, are immutable. Said this, if every different object of a class has a different value (state), that value is a perfect hash code: zero collisions, total entropy, homogeneus distribution...
If i want to find the object reference of the wrapper class object a
in the above code.How do i do it?
Using System.identityHashCode()
In Java, hashcode helps to give a quick comparaison hint between two objects. As two different Integer having same value are equal, they should have same hash. That's the reason why the value was taken for hash.

Is it useful to log an object hashcode?

I see a lot of the following line in projects I took over:
log.debug(submitObject(" + object + ")");
log.debug(registerUser(" + user + ")");
and so on.
In the logs this prints out something like:
SubmitObject(java.lang.Object#13a317a)
Is it useful to log just the object type and its hashcode? Say I want to know the name of the user object but I only have the hashcode, would it be possible for me to reconstruct the object based on the hashcode?
From the javadoc for object.toString()
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method. The toString method for class Object
returns a string consisting of the name of the class of which the
object is an instance, the at-sign character `#', and the unsigned
hexadecimal representation of the hash code of the object. In other
words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
Returns: a string representation of the object.
I myself always override the toString() of a custom object so it prints out all the fields of the object. Should I start printing the object code instead?
You could use ReflectionToStringBuilder from org.apache.commons, if you do not have access to source code, or if you do not want implement toString for change existing code.
For Example:
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("User : "
+ reflectionToStringBuilder.toString(user ,
ToStringStyle.MULTI_LINE_STYLE))
}
"LOGGER.isDebugEnabled() is very important as toString Operation, or reflectionToStringBuilder, will be executed before calling log.debug, so you do not want such expensive operations.
ReflectionToStringBuilderJavaDoc: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/builder/ReflectionToStringBuilder.html
No, keep overriding toString() which is much more useful. The default toString() is practically useless except that it at least shows what the class instance is.
That hash code is a randomly assigned value. It is only useful if you want to check you had the same object in a previous log, or a different one (i.e. very rarely)

hashCode() purpose in Java

I read in a book that hashCode() shows a memory area which helps (e.g. HashSets) to locate appropriate objects in memory. But how can that be true if we cannot manipulate memory in Java directly? There are no pointers, in addition to it objects are created and moved from one place to another and the developer doesn't know about it.
I read that realization like hashCode() {return 42;} is awful and terrible, but what's the difference if we can't instruct VM where to put our objects?
The question is: what is the purpose of hashCode() on deep level if we can't manipulate memory?
I read in a book that hashCode() shows a memory area which helps (e.g. HashSets) to locate appropriate objects in memory.
No, that's a completely bogus description of the purpose of hashCode. It's used to find potentially equal objects in an efficient manner. It's got nothing to do with the location of the object in memory.
The idea is that if you've got something like a HashMap, you want to find a matching key quickly when you do a lookup. So you first check the requested key's hash code, and then you can really efficiently find all the keys in your map with that hash code. You can then check each of those (and only those) candidate keys for equality against the requested key.
See the Wikipedia article on hash tables for more information.
I like Jon Skeet's answer (+1) but it requires knowing how hash tables work. A hash table is a data structure, basically an array of buckets, that uses the hashcode of the key to decide which bucket to stick that entry in. That way future calls to retrieve whatever's at that key don't have to sift through the whole list of things stored in the hashtable, the hashtable can calculate the hashcode for the key, then go straight to the matching bucket and look there. The hashcode has to be something that can be calculated quickly, and you'd rather it was unique but if it isn't it's not a disaster, except in the worst case (your return 42;), which is bad because everything ends up in the same bucket and you're back to sifting through everything.
The default value for Object#hashCode may be based on something like a memory location just because it's a convenient sort-of-random number, but as the object is shunted around during memory management that value is cached and nobody cares anyway. The hashcodes created by different objects, like String or BigDecimal, certainly have nothing to do with memory. It's just a number that is quickly generated and that you hope is unique more often than not.
A hash code is a just a "value". It has nothing more to do with "where you put it in memory" than "MyClass obj = new MyClass()" has to do with where "obj" is placed in memory.
So what is a Java hashCode() all about?
Here is a good discussion on the subject:
http://www.coderanch.com/t/269570/java-programmer-SCJP/certification/discuss-hashcode-contract
K&B says that the hashcode() contract are :
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.
If two objects are unequal according to the equals(Object) method, there's no requirement about hashcode().
If calling hashcode() on two objects produce different integer result, then both of them must be unequal according to the
equals(Object).
A hashcode is a function that takes an object and outputs a numeric value. The hashcode for an object is always the same if the object doesn't change.
Functions like hashmaps that need to store objects, will use a hashcode modulo the size of their internal array to choose in what "memory position" (i.e. array position) to store the object.
There are some cases where collisions may occur (two objects end up with the same hashcode, and that, of course, need to be solved carefully). For the details, I would suggest a read of the wikipedia hashmap entry
HashCode is a encryption of an object and with that encryption java knows if the two of the objects for example in collections are the same or different . (SortedSet for an example)
I would recommend you read this article.
Yes, it has got nothing to do with the memory address, though it's typically implemented by converting the internal address of the object. The following statement found in the Object's hashCode() method makes it clear that the implementation is not forced to do it.
As much as is reasonably practical, the hashCode method defined by
class Object does return distinct integers for distinct objects. (This
is typically implemented by converting the internal address of the
object into an integer, but this implementation technique is not
required by the JavaTM programming language.
The hashCode() function takes an object and outputs a numeric value, which doesn't have to be unique. The hashcode for an object is always the same if the object doesn't change.
The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal.
By definition, if two objects are equal, their hash code must also be equal. If you override the equals() method, you change the way two objects are equated and Object's implementation of hashCode() is no longer valid. Therefore, if you override the equals() method, you must also override the hashCode() method as well.
For more, check out this Java hashcode article.

HashMap Not Calling Object.equals?

I wrote a class that overrides the equals(Object) method in class Object to compare objects of the class type to other objects of a class type using the object's instance values.
When I put an instance of the object in a HashMap as the key, and then call get(Object) on the map with a new but identical object as the key, it returns null.
I've tried passing a new, identical object to the equals method and it returns true, so the problem isn't my comparison code.
From what I've gathered through debugging, the equals(Object) method in my object is never called.
But if you use a String key in a HashMap and then pass a new instance with identical characters to get(Object), it returns the value successfully.
Why is this happening? What do I have to do to have HashMap test keys based on MY equals method?
You need to also override Object.hashcode(). Take a look at the link, as it specifies that hashcode() and equals() have a contract to ensure proper functionality in HashTable's, HashMap's, and HashSet's.
In a HashMap, values are stored in buckets, which are reached by the hashcode of the key. Once the proper bucket is found, the equals method is then applied to each member of the bucket until equality is determined. Because of this, it is important to make sure that your hash algorithm 'hashes well'.
You should also override hashCode otherwise it won't work as HashMap (as the name suggests) equates equality based on a collection of hashes. The Java "honour code" for overriding equals is that you should also override hashCode at the same time.

Categories