Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Are immutable objects (other than String like Integer and other wrapper classes etc.) good for hashmap keys?
Can anybody explain how?
If immutable, the object's hashcode wont change and it allows caching the hashcode of different keys which makes the overall retrieval process very fast.
Also for mutable objects ,the hashCode() might be dependent on fields that could change, if this happens you wont be able to find the key (and its value) in the HashMap since hashCode() returns different value.
You can find the answer here: How HashMap works in Java
String, Integer and other wrapper classes are natural candidates of HashMap key, and String is most frequently used key as well because String is immutable and final,and overrides equals and hashcode() method. Other wrapper class also shares similar property. Immutabiility is required, in order to prevent changes on fields used to calculate hashCode() because if key object return different hashCode during insertion and retrieval than it won't be possible to get object from HashMap. Immutability is best as it offers other advantages as well like thread-safety, If you can keep your hashCode same by only making certain fields final, then you go for that as well. Since equals() and hashCode() method is used during retrieval of value object from HashMap, its important that key object correctly override these methods and follow contact. If unequal object return different hashcode than chances of collision will be less which subsequently improve performance of HashMap.
There is also another stack for the discussion: Why are immutable objects in hashmaps so effective
Both hashcode and equals method are used in put and get method of HashMap. You need to make sure you can always get the value object from the map after you put it with the key object. No matter you change the key object or not. But Immutable object is good enough to achieve that.
yes because it is unchangeable.
Lets assume that i am having one class
MyKey key = new MyKey("shreyansh"); //assume hashCode=1234
myHashMap.put(key, "value");
// Below code will change the key hashCode() and equals()
// but it's location is not changed.
key.setName("jogi"); //assume new hashCode=7890
//below will return null, because HashMap will try to look for key
//in the same index as it was stored but since key is mutated,
//there will be no match and it will return null.
myHashMap.get(new MyKey("shreyansh"));
here while accessing that using key "Shreyansh" it will return nulll
If you object is immutable and implements hashcode/equals correctly, you are fine to use them as keys in a hashmap.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Can ThreadLocal be used as Key in HashMap?
If so, how does it work and is it generally a bad idea? What should I look out for and be aware of?
You can use ThreadLocal as a HashMap key like any other object. Whether it has any meaning is a different topic.
Basically you can have problems if you use a mutable object as a key for things like HashMap, HashSet and so on, because those classes usually use hashCode() (hence the name) to put stuff in buckets and retrieve it. So if you use a mutable object as a key, then change the object (in a way the hashCode changes) and then try to retrieve the entry by key, you will not find the entry anymore as the map will look in the wrong bucket for the entry.
In the case of ThreadLocal this would not be a problem, as it does not override equals() and hashCode() and thus the hashCode() will not change if you change the object, so you could safely use the ThreadLocal as key.
As Jaroslaw Pawlak commented, since ThreadLocal doesn't implement hashCode() and equals() it is not suitable for the key in HashMap, at least if you expect it to be well behaved.
Even if it did, it would be useless. Considering the use-case of ThreadLocal, it would be far clearer to use the contained object as the key.
Having a map with one ThreadLocal (with thread specific contents) mapping just ends up with having the internal map of ThreadLocal (the one that maps the thread to the value) being used for the actual mappings.
Not to mention that ThreadLocal instances are somewhat recommended against. The common use cases they have are solved by introducing "native" threadlocal classes, such as java.util.concurrent.ThreadSafeRandom.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I was checking code of contains() method of Collection and could not find hashcode() usage. Here is the link of contains() method javadoc
Why no optimisation on ArrayList or LinkedList implementation?
Because it is not necessarily an optimization.
It is only an optimization to call hashCode before equals if hashCode is significantly cheaper than equals. If you knew that the object's implementation of hashCode caches the hash code value AND that you had previously called hashCode on the object, then it could be faster to call hashCode first. But if either of those was not true, then you are likely to find that:
the hashCode call is at least as expensive as the equals call (after all, hashCode cannot "short circuit" like a well-implemented equals often can), and
when the hash code values are equal, you still need to call equals.
The analysis gets very complicated ... but suffice it to say that in a lot of cases (considering all implementations of hashcode and equals, distributions of equal versus unequal elements, etc) using hashCode would be an ANTI-optimization.
Having said that, if you have a use-case where it would improve things to use hashCode as an optimization, you are free to implement your own custom collection classes. Alternatively, you could optimize the element classes equals and hashCode methods so that equals itself checks a (cached) hash value.
The reason ArrayList does not need to use the hashCode() method because the ordering is determined by the insertion order.
The hashCode() method is for objects in a HashSet or objects that are used as keys in a HashMap.
hash codes are just optimizations. Eventually, a Collection#contains or Map#get call must call equals to check that the passed object is really there, and not another object that happens to have the same hash code. If you look at specific implementations like HashSet or HashMap, you'll see that hashCode() is used along the way as an optimization.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In java,We can use Object.hashCode() to get the object's hashcode, that, in turn, can we use the hashcode to get the object? But how? Is there any existing method to solve this problem?
Hashcode do not work that way. They are meant to be a hint whether two objects are equal. From Object javadoc :
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.
As different object may have same hashcode, there cannot exist a way to get an object from its hashcode. If you have such a need, do use a Map and store objects with a key. But even there a Map will have only one value per key (still from javadoc : A map cannot contain duplicate keys; each key can map to at most one value)
This question already has answers here:
Difference between HashSet and HashMap?
(20 answers)
Closed 4 years ago.
I am a beginner in Java, so this may be a dumb question.
Why we need hashSet in Java?
I just learned that Java hashSet is actually implemented with HashMap. In my understanding, whenever we use hashSet, we can always use hashmap, so why we need hashSet in java?
Thanks
You can google differences between HashMap and HashSet to understand more.
HashMap is an implementation of Map interface;
HashSet is an implementation of Set Interface;
HashMap stores data in form of key value pair;
HashSet stores only objects;
Put method is used to add element in map;
Add method is used to add element is Set;
In hash map hashcode value is calculated using key object.
Here member object is used for calculating hashcode value which can
be same for two objects. So equal() method is used to check for
equality: if it returns false, that means two objects are different.
Got the info from here.
You can, and you can even further argue that why we need ArrayList because you can see an ArrayList as a map with an integer as index, then you can use an HashMap and use integer as key and then you don't really need List anymore.
There are specific purpose and semantic meaning for different data structure, for example, Set is a collection that will not allow duplicate. Map aimed for providing key-value lookup. If you only want a collection to store non-duplicated objects, why use a Map that is aimed for other purpose?
This question already has answers here:
Why do I need to override the equals and hashCode methods in Java?
(31 answers)
Closed 7 years ago.
I am running into this weird issue where I am iterating over a list of responses. when I try to get the answer from each response by the question, most of them get the answer correctly except one where getting the answer from the hashmap gives null. I have ran the debug mode in eclipse, and compared the question that I try to get its value from the hashmap getAnswerMap() with the one inside that hashmap and both seem to be exactly the same, but I still get null.
for (SurveyResponse response : responses) {
MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question);
....
....
}
Then, I thought it is a hashcode issue, so I added another ugly line of code to check hashcodes, and they actually have the same hashcode and the additional following line worked and did set answer correctly.
for (SurveyResponse response : responses) {
MultipleChoiceAnswer answer = (MultipleChoiceAnswer) response.getAnswerMap().get(question);
for (Entry entry: response.getAnswerMap().entrySet()) {
if (entry.getKey().hashCode() == question.hashCode()) answer = (MultipleChoiceAnswer) entry.getValue();
....
....
}
However, this is very ugly and I would really like to get the answer correctly from the hashmap. Any suggestions?
UPDATE:
calling both hashCode() and equals() method on both objects shows that both have equal hashcodes and equals() returns true. I suspect that as one of the answers down indicate, the problem might be that the question was inserted with a different hashcode when it was inserted in the hashmap. Therefore, calling the get method in question returns null because the object I am trying to get does not have the same hashcode as the old one. Extremely helpful answers guys!
One thing to watch out for: Make sure the class you're using as a key is immutable -- otherwise, a key will hash to one thing when you put it in, but something different when you take it out.
Edit: It doesn't have to be immutable, but it has to be true that it can only be changed in a way that doesn't change the hashcode. Making the entire object immutable is the simplest way to do that, but it's not the only way.
One more glass ball guess:
You have an equals method like this one:
class Question {
// ...
public boolean equals(Question q) {
// do intelligent comparison
}
public int hashCode() {
// calculate hash code
}
}
But here you don't really override the equals(Object) method from Object, but simply declare a new one beside this. The HashMap does not know anything about your new method, it will simply call the original one for comparing your key object in the map with the query key (after finding one with matching hashCode).
Declare the method like this, instead:
#Override
public boolean equals(Object o) {
if(! (o instanceof Question))
return false;
Question q = (Question)o;
// do intelligent comparison
}
(The #Override annotation lets the compiler check that you are really overriding a method here, not just creating a new one.)
To make an object an 100% deterministic key with a HashMap you need to override hashCode() and equals() where they are consistent in that equals() always returns true when the hashCode()s are the same.
Here is an old article from Brian Goetz on IBM developerWorks, but the contents are still applicable today:
Why override equals() and hashCode()?
What would happen if Integer did not
override equals() and hashCode()?
Nothing, if we never used an Integer
as a key in a HashMap or other
hash-based collection. However, if we
were to use such an Integer object for
a key in a HashMap, we would not be
able to reliably retrieve the
associated value, unless we used the
exact same Integer instance in the
get() call as we did in the put()
call. This would require ensuring that
we only use a single instance of the
Integer object corresponding to a
particular integer value throughout
our program. Needless to say, this
approach would be inconvenient and
error prone.
The interface contract
for Object requires that if two
objects are equal according to
equals(), then they must have the same
hashCode() value. Why does our root
object class need hashCode(), when its
discriminating ability is entirely
subsumed by that of equals()? The
hashCode() method exists purely for
efficiency. The Java platform
architects anticipated the importance
of hash-based collection classes --
such as Hashtable, HashMap, and
HashSet -- in typical Java
applications, and comparing against
many objects with equals() can be
computationally expensive. Having
every Java object support hashCode()
allows for efficient storage and
retrieval using hash-based
collections.
It's likely that you haven't overridden equals(..) correctly - it is a requirement for a HashMap to work correctly