Understanding the workings of equals and hashCode in a HashMap?

You have overidden equals without overriding hashCode You must ensure that for all cases where equals returns true for two objects hashCode returns the same value. The hash code is a code that must be equal if two objects are equal (the converse need not be true). When you put your hard-coded value of 9 in, you satisfy the contract again.

You have overidden equals without overriding hashCode. You must ensure that for all cases where equals returns true for two objects, hashCode returns the same value. The hash code is a code that must be equal if two objects are equal (the converse need not be true).

When you put your hard-coded value of 9 in, you satisfy the contract again. In your hash map, equality is only tested within a hash bucket. Your two Monday objects should be equal, but because they are returning different hash codes, the equals method isn't even called to determine their equality - they are put straight into different buckets, and the possibility that they are equal isn't even considered.

6 It is also worth noting that the equals function is implemented incorrectly. It only works on this case because the two "Monday" string literals are interned and therefore have the same reference. – Mark Byers Dec 12 '09 at 19:07 1 Yes, well spotted!

Quite correct. – David M Dec 12 '09 at 19:08 The equals method should also be able to cope with null and arguments of different classes (note subtypes). If you keep equals (and hashCode) to a standard form, then it is trivial to implement correctly (even a machine could code it!).

– Tom Hawtin - tackline Dec 12 '09 at 19:18 Even if two entries end up in the same bucket they aren't necessarily compared. The (Sun) implementation keeps a record of the hash code so that it doesn't need to be recomputed. This is also compared as a quick check before calling equals.

– Tom Hawtin - tackline Dec 12 '09 at 19:20 1 Does size() express only the number of keys used? – omgzor Dec 12 '09 at 20:51.

When you don't override the hashCode() method, your ToDos class inherits the default hashCode() method from Object, which gives every object a distinct hash code. This means that t1 and t2 have two different hash codes, even though were you to compare them, they would be equal. Depending on the particular hashmap implementation, the map is free to store them separately (and this is in fact what happens).

When you do correctly override the hashCode() method to ensure that equal objects get equal hash codes, the hashmap is able to find the two equal objects and place them in the same hash bucket. A better implementation would give objects that are not equal different hash codes, like this: public int hashCode() { return (day! = null)?Day.hashCode() : 0; }.

– David M Dec 12 '09 at 19:07 2 The hash code is used by the HashMap to quickly find objects without having to compare every object. If all your hashcodes are the same, it will cause everything to go into the same bucket which will slow things down a lot. – Mark Byers Dec 12 '09 at 19:09 1 Because that reduces the number of hash collisions, which is vital for good performance.

In the extreme case of hashCode() returning the same value for all objects, the HashMap degenerates to a list, and all those nice O(1) apperations are suddenly O(n). – Michael Borgwardt Dec 12 '09 at 19:11 @Michael - But the same is true at the opposite extreme - your list of items in a single has bucket becomes a list of one item hash buckets. You need to get a balance, and there is certainly no rule of thumb saying that the right balance is obtained by making sure that inequality gives different hash codes.

– David M Dec 12 '09 at 19:17 @David - there is exactly that rule of thumb, by design of a hash table. From the hashCode() docs (java.sun.Com/javase/6/docs/api/java/lang/…): the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables. – Avi Dec 12 '09 at 19:23.

I cannot emphasize enough that you should read Chapter 3 in Effective Java (warning: pdf link). In that chapter you will learn everything you need to know about overriding methods in Object, and in particular, about the equals contract. Josh Bloch has a great recipe for overriding the equals method that you should follow.

And it will help you understand why you should be using equals and not == in your particular implementation of the equals method. Hope this helps. PLEASE READ IT.(At least the first couple items... and then you will want to read the rest :-).

-Tom.

Not to mention, a recipe for overriding hashCode() too! – Tom Dec 12 '09 at 20:08.

When hashCode is uncommented, HashMap sees t1 and t2 as being the same thing; thus, t2's value clobbers that of t1. To understand how this works, note that when hashCode returns the same thing for two instances, they end up going to the same HashMap bucket. When you try to insert a second thing into the same bucket (in this case t2 is being inserted when t1 is already present), HashMap scans the bucket for another key that is equals.In your case, t1 and t2 are equals because they have the same day.

At that point, "payBills" clobbers "doLaundry". As for whether t2 clobbers t1 as the key, I believe this is undefined; thus, either behavior is allowed. There are a few important things to think about here: Are two ToDos instances really equal just because they have the same day of the week?

Whenever you implement equals, you should implement hashCode so that any two objects that are equals also have the same hashCode values. This is a fundamental assumption that HashMap makes. This is probably also true of anything else that relies the hashCode method.

Design your hashCode method so that the hash codes are evenly distributed; otherwise, you won't get the performance benefits of hashing. From this perspective, returning 9 is one of the worst things you can do.

The Implementing equals and Implementing hashCode topics on javapractices. Com might be helpful as well.

When you comment, it returns 3; because hashCode() inherited from the Object is ONLY called which returns 3 different hashcodes for the 3 ToDos objects. The unequal hashcodes means the 3 objects are destined to different buckets and equals() return false as they are the first entrant in their respective buckets. If the hashCodes are different it is understood in advance that the objects are unequal.

They will go in different buckets. When you uncomment, it returns 2; because here the overridden hashCode() is called which returns the same value for all the ToDos and they all will have to go into one bucket, connected linearly. Equal hashcodes don't promise anything about the equality or inequality of objects.HashCode() for t3 is 9 and as it is the first entrant, equals() is false and t3 inserted in the bucket- say bucket0.

Then t2 getting the same hashCode() as 9 is destined for the same bucket0, a subsequent equals() on the already residing t3 in bucket0 returns false by the definition of overridden equal(). Now t1 with hashCode() as 9 is also destined for bucket0, and a subsequent equals() call returns true when compared with the pre-existing t2 in the same bucket. T1 fails to enter the map.So the net size of map is 2 -> {ToDos@9=cleanAttic, ToDos@9=payBills} This explains the importance of implementing both equals() and hashCode(), and in such a way that the fields taken up in determining equals() must also be taken when determining hashCode().

This will guarantee that if two objects are equal they will always have same hashCodes. HashCodes should not be perceived as pseudo-random numbers as they must be consistent with equals().

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions