This presentation is part of Marcus Biel’s free Java 8 course focusing on clean code principles. It concludes a series where we go over all the methods of the java.lang.Object class. Since hashCode and equals are two of java.lang.Object’s methods which follow a contract that binds them together, it makes sense to show both methods together. In fact, they are bound in such a way that we cannot implement one without the other and expect to have a well-written class. Knowing all the details about these two methods is essential to becoming a better Java programmer. So what do these two methods do?
Ecosystem Interactions Class Discussion Presentation in Blue Green Lined Styl...
Hash code and equals
1. 2016, Marcus Biel, http://www.marcus-biel.com/
equals and hashCode
Marcus Biel,,Software Craftsman
www.marcus-biel.com
2. 2016, Marcus Biel, http://www.marcus-biel.com/
equals and
hashCode
This presentation is about the two methods hashCode and equals.
hashCode and equals both follow a contract,
that ties them closely together,
3. 2016, Marcus Biel, http://www.marcus-biel.com/
equals and
hashCode
which is also why I am talking about both methods
in just one presentation
4. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public boolean equals(Object o)
Let’s start with the equals method.
What does it do, what’s it useful for?
5. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public boolean equals(Object o)
The equals method is used to compare two objects for equality,
similar to the equals operator that is used for primitive values.
6. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public boolean equals(Object o)
Before we are able to implement the equals method,
we need to come up with a proper design first.
7. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public boolean equals(Object o)
Actually many developers just skip the design phase and
simply click on “auto generate”,
8. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public boolean equals(Object o)
which may lead to severe bugs or
at least to suboptimal performance.
Let me show you how you can properly do it.
9. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
myOldCar
myPorsche
mumsCar
dadsCar
First of all you have to define what it is in your specific program,
that makes two car instances equal, or unequal.
10. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
In your program,
are two cars equal when they have the
same manufacturer maybe?
11. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
When they have the same manufacturer and color?
12. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
the same engine?
13. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
or the same number of wheels?
14. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
The same top speed?
15. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
The same vehicle identification number or VIN in short?
16. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Based on the knowledge of the business you are working in,
you have to decide which fields are identifying
and which fields are redundant and
not helpful for the equal comparison.
17. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Besides, for improved performance, you need to define
in which order you want to compare the attributes.
18. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Are there any fields that have a high chance to be unequal?
Are there fields that may be compared faster then others?
To implement a meaningful equals method,
you must first analyze all these aspects in great detail.
19. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Let’s go through this process with my example.
I would assume that the car’s top speed relates
to the type of the engine in some form;
20. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?top speed?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
so that seems to be a redundant field that will not be helpful
for the equals implementation, so let’s remove it.
21. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
number of wheels?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Let’s say the number of wheels is always four
in our specific example,
so number of wheels would also not help us to differentiate a car.
22. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
What about the VIN?
23. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Well,
this again depends on the type of program you want to create.
For a public authority, like the police,
this one is probably the only proper way of identification.
24. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
But what about a program used by the manufacturer itself?
While the car is still being build and not sold yet,
I would assume the VIN is of less importance.
But I personally wouldn’t know that in detail.
25. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
This is what YOU will have to clarify with the business people of
YOUR company or YOUR department.
26. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
Based on their knowledge,
you have to select which attributes to compare in which order.
27. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
In my artificial example here
I’m the developer as well as the business analyst.
28. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
VIN?
So for my example I just arbitrarily define that
two cars with different VIN numbers can be seen as equal.
29. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
Therefore
I will not include this field in my equals comparison later on.
30. 2016, Marcus Biel, http://www.marcus-biel.com/
When are two objects equal?
myOldCar
myPorsche
mumsCar
dadsCar
color?
engine?
manufacturer?
myOldCar
myPorsche
mumsCar
dadsCar
Now before you think - “that’s it,
I am sorry -there is actually some more theory to cover
31. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
In the introduction I already told you that
there is a contract of equals and hashCode we have to fulfil.
32. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
First of all, there are five conditions
our equals implementation has to comply with.
Believe me, it looks much more scary then it actually is.
33. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Let’s go through each of them slowly.
34. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Reflexivity - An object must be equal to itself,
so that when I call myOldCar.equals(myOldCar) it returns true.
35. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
I think this makes sense
and
should be easy to understand.
36. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Symmetry –
two objects must agree whether or not they are equal
37. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
If myOldCar.equals(someOtherCar) returns true,
then someOtherCar.equals(myOldCar) must also return true.
38. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
This sounds obvious and very simple,
when in fact it is not such a simple condition
when it comes to inheritance.
39. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
If you have a Car class and a BMW class
which is extending the Car class,
it could happen that your BMW is equal to a Car,
40. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
but the same Car is not equal to the BMW,
as every BMW is a Car,
but not every Car is a BMW.
41. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
So the symmetry rule can actually lead to some nasty problems.
There are quite a few interesting articles online discussing
potential symmetry issues of the equals method.
42. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Cover each contract condition with a dedicated unit test
to make sure your class stays fully compliant with the contract.
43. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Our next condition is Transitivity.
If one object is equal to a second,
and the second to a third, the first must be equal to the third
44. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
This rule sounds much more complicated then it actually is.
If object a is equal to object b and object b is equal to object c,
they should all be equal to each other, so that c is also equal to a.
45. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
Consistency - If two objects are equal,
they must remain equal for all time,
unless one of them is changed.
46. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
So when you repeatedly compare the
same two objects with the equals method,
it should always return the same result.
47. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
In other words,
calling the equals method should not alter the object in any way.
48. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
The last rule “Null returns false”
is what Josh Bloch calls
“Nonullity”.
49. 2016, Marcus Biel, http://www.marcus-biel.com/
equals contract
Reflexivity
an object must be equal to itself
Symmetry
two objects must agree whether or not they are equal
Transitivity
if one object is equal to a second, and the second to a third, the first must be equal to the third
Consistency
if two objects are equal they must remain equal for all time, unless one of them is changed
Null returns false
all objects must be unequal to null
When null is given as a parameter to any equals method,
this should always return false and never throw a
NullPointerException.
50. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public int hashCode()
So now you know quite a bit about the equals method,
but what is the hashCode method actually useful for?
51. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public int hashCode()
For processing,
similar objects are usually put into a “collection”.
Such a collection in Java is like a more powerful array,
or an array on steroids as I often call it.
52. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public int hashCode()
Besides other things,
it allows you to look up objects not only
based on their index position,
but also based on their specific values.
This is where the equals method comes into play.
53. 2016, Marcus Biel, http://www.marcus-biel.com/
@Override
public int hashCode()
To speed up this look up process,
the Java creators added specific hash based containers,
that will use the hash value as a grouping mechanism
to reduce the number of equal comparisons needed.
54. 2016, Marcus Biel, http://www.marcus-biel.com/
-12944831
dadsCar
7
mumsCar myOldCar
-9897
myPorsche
In the optimal case,
each object that is considered unequal by the
equal method will also return a different hashCode.
This hashCode is used to group the objects in so called “buckets”.
55. 2016, Marcus Biel, http://www.marcus-biel.com/
-12944831
dadsCar
7
mumsCar myOldCar
-9897
myPorsche
Now in this optimal case,
you will be able to find each object simply by
a lookup based on it’s hash value.
56. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
39929191
mumsCar
-391
myOldCar
dadsCar
myPorsche
However, there may also be something called “Hash Collisions”,
where two unequal objects will share the same hashCode,
in which case they end up in the same bucket.
57. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
39929191
mumsCar
-391
myOldCar
dadsCar
myPorsche
Now if I am looking for dadsCar,
I have to lookup the correct bucket based on the hashCode
minus three hundred ninety one that dadsCar will return.
58. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
39929191
mumsCar
-391
myOldCar
dadsCar
myPorsche
However as there is a hash collision,
I will on top have to do an equals comparison
on a list of two cars in this case.
59. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
42
myOldCar
myPorsche
mumsCar
dadsCar
A technically legal but inadmissible bad performing hashCode
implementation could statically return 42 for all objects.
60. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
42
myOldCar
myPorsche
mumsCar
dadsCar
In this case however the whole hashCode logic would not help at all
- in the end you would have to do an equals
comparison on the entire list of cars, just as if the
hashing logic had never existed.
61. 2016, Marcus Biel, http://www.marcus-biel.com/
Hash collisions
42
myOldCar
myPorsche
mumsCar
dadsCar
Okay, now that I have showed the general idea of the the
hashCode method,I have to further show you about the contract
that the hashCode method has to fulfil so that both
hashCode and equals methods will work as designed.
62. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
The first condition that has to be
fulfilled by the hashCode method is:
63. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
For any two objects return
same hashCodes when equals returns true
64. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
To achieve this,
use the same identifying attributes for both methods,
in the same order.
65. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
Don’t worry too much if you don’t fully understand what I mean.
As soon as you finish this introduction of the hashCode contract,
You should jump to my video of this presentation
to see a practical example.
66. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
• When hashCode is invoked more then once on
the same object, it must consistently return the
same int value as long as the object is not
changed
When hashCode is invoked more then once on the same object,
it must consistently return the same
int value as long as the object is not changed.
67. 2016, Marcus Biel, http://www.marcus-biel.com/
hashCode contract
• For any two objects return same hashCodes
when equals returns true
• When hashCode is invoked more then once on
the same object, it must consistently return the
same int value as long as the object is not
changed
This rule is similar to the equals consistency rule
I introduced you before.
Both equals and hashCode methods
must return consistent results.
68. 2016, Marcus Biel, http://www.marcus-biel.com/
Overwrite hashCode whenever
you overwrite equals
To fulfil this contract you should overwrite hashCode
whenever you overwrite equals and vice versa.
69. 2016, Marcus Biel, http://www.marcus-biel.com/
Also, when you add or remove attributes from your class you
will most probably also have to adjust your
equals and hashCode methods.
Overwrite hashCode whenever
you overwrite equals
70. 2016, Marcus Biel, http://www.marcus-biel.com/
aim to return different hashCodes
when equals returns false
Last but not least,
aim to return different hashCodes when equals returns false.
This is not a hard and fast rule,
but it will improve the performance of
your program by minimizing the number of hash collisions.
71. 2016, Marcus Biel, http://www.marcus-biel.com/
aim to return different hashCodes
when equals returns false
To the extreme,
the hashCode contract would allow to
statically return 42 for all objects.
As Josh Bloch states in his book “Effective Java”
72. 2016, Marcus Biel, http://www.marcus-biel.com/
aim to return different hashCodes
when equals returns false
however, this could result in quadratic rather
then linear execution time
and therefore could be the difference between
working and not working.