so this is a continuation from the previous video where we are talking about
equals and hash Code now just before I go any further I want to make sure that I add
the @ override before so we talked about how that is essential to make sure that
the compiler is checking to see whether you have the right signature for the
method and I deleted it right at the end of the last video when I was showing you how
to create an empty stub using the intelliJ functionality so again just as a
recap command N which is alt insert on a PC now I can go to override methods and I can go through and
override I can't do equals now because it's not in the list and that's because I've
already successfully overridden it that's normally where you choose it and we can take it
from there so anyway I put that back so that's good to so now that we've written
our first equals method we change it now to use an object instead of a heavenly body
because we talked about how we need it to do that because we weren't
overloading the method we are overriding it is an important distinction between the two there
so what does this equals method do first or do in general it first checks
to see if it's been compared to itself we talked about that that's on line 39
if it's checking for itself it's going to return true because we discussed how from
an object's point of view equals equals just returns true if the object you're
comparing is the same object in memory next it does a similar tests to the
instance of tests we saw in the last video when we're looking at the string
class with that said in order to make sure that sub classes do not compare
equal what we doing is we check the actual class of the object being
compared against the class of the object the method is in now if we tried to call the
get class method of null we get a null pointer exception so that's why we have
to have a test first on that line 45 the first part to test for
null first null will fail the instance of checks so an explicit test for null is required
when using instant off and obviously so that we know what's going on we
are printing out the results on line 43 and 44 but we won't leave that in the final code
but it's also useful to see when our equals method is called as well as
explaining what the test is doing and finally because we've just we just
comparing names
we establish that's going to be our criteria for an equals
match in the heavenly body given that the string class already has an equals
method we can cast the object we comparing to a heavenly body and then use a string
equals method to compare its name against the name of the current object
which has of course is this.name so we know this class is safe and won't throw an exception because
we've already checked on line 45 for null and also ensure that object is a
heavenly body as well on that same line so you think that we're ready to run
this but actually we are not really ready to run this yet and that's because if you recall
I talked about it in length in the previous video about needing the hash code how
we need to override both equals and hash Code methods at the same time so technically
it's not going to be correct but because it's very informative lets us run it now
anyway but bearing in mind that of course it's not going to be valid completely until
we implement the hash code methods so we go back to main and I'm going to run it so there's two things we
can actually see from this output and number one and most importantly our
equals method was not called so how do we know well if you go back and have a
look at our heavenly body code we added some system out print lines there to
actually check to see or to tell us what was being checked and that has
shown in the log as you on the right hand side so that's number one
and secondly pluto is still showing twice so this is the reason why you want
to implement hash code because we haven't done that we haven't overwritten hash code
the second Pluto was put into a different bucket now because there wasn't
already something in the bucket there's no need to call equals so both
observations come down to the same cause so effectively the Pluto is being
repeated twice
so lets go back and look at implementing that I'll close down the string java source
code we don't need it anymore we go back to heavenly body and let's implement our hash code so I'm just going
to use the command and go to override methods and incidentally I can also use
I believe it's ALT insert on a PC but I can also use control O on a Mac
and that will come up automatically to the override as opposed to that extra
menu if you want to see what it is on your operating system
you can see up here it will be override methods for me that's the command o for a Mac look at what the equivalent
key shortcut is on your PC or Linux machine and you can do that as a
shortcut so I'm gonna do command o again and I'm going to override the hash code and
that's giving us some basic code there as you can see but we're going to change that so
in terms of the implementation it actually appears extremely easy and the
reason is because the String class has a hash Code method and because we're
comparing only strings because we decided in the equals method our comparison
is going to be just the name of the heavenly body so you think that we could
just would seem that we just generate the hash code for the body's name so in
other words we could do something like this
....so the hash code in this case that we're calling is
the hash code method from the String class now this would actually work here
and that's because we've typed the sets and the map using generics so there's
little danger of comparing say a heavenly body to a string but it's not
really good practice though to do this because a heavenly body called pluto would
probably have a different hash code to the string pluto now how you generate hash codes
is pretty much up to you as long as the same object will always generate the
same hash code during any execution of your program and also as long as objects
that compare equal have the same hash code once that's done then the
requirement is satisfied now if you search for overriding on the internet you
will actually find some recommendations that you can just return 0 every instances of
an object will have the same hash code which certainly meets the
requirement that two objects that compared equal have the same hash code and also
means that no matter how many times you generate a hash Code from an object it would
always be the same in that scenario so with that suggestion returning 0 in other
words meets the requirements for a hash code method but you think about it sort
of misses the purpose of hashing in the first place
now if every object of a hash collection ends up in the same bucket and you totally lose
the performance benefits
of using hash collection class the performance in that case will drop
to that of a linked list or a similar structure and that's because once the
single bucket has been located which is bucket 0 the items will each need to be compared to see
if the required one is in their so it's very much less sufficient to doing it that way
now adding a number to the names hash code will make it different and that's what we
will actually do here so any number that doesn't risk overflowing an integer will do so
will just use 57 in this case is just enough not to cause problems and well also print out a message
temporarily so that you can see the hash code is being used so what would do is go back to our
hash code method and we're going to add to the end of that a number and as I
mentioned we will use the number 57 because it is small enough not to cause any problems and
that then guarantees that we've got a number a non-zero number that's been
returned for each of our hashes so again we're using the code that comes back
from a string but we're adding 57 to that as well so its a non-zero number because hash code from the
string source code is returning its own hash code and we're adding the number 57
to that so lets also print a message in their or we will just indicate that it has been called so....
....and now in theory if you go back to our main now we have
implemented both equals and hash Code we should see our debugging codes
showing when we run the app or when we run the
application so to do that we run it and now you can see hashcode called so that's good and then we
can also see over here
object class is class.com.timbuchalka.HeavenlyBody you can see the comparisons
object and this is returning the same information and the good of course down here now
that we've done that you can see that Pluto is now only in the list once its only been added once
now and the other thing to note is if you recall with our code we had added our second pluto
that we added we use
842 for the orbital period but 248 which was the first entry for pluto has
been added which is the correct one and that tells us that the duplicate the
second one wasn't added and the this now fits the behavior of a set that an object
will not be added if already exists and we can clearly say their that only the
original pluto has been added now we have looked at the two rules for hash code method
we have not fully discuss the rules for equals so the 5 rules father I'm going to just bring up a
link here it can be found and this is a resource there will be a link to in this video
Resources section and you can open that up but I'll go and put it in a new tab
come down to equals as you can see their we got some code there for information about hash
code but also some information about equals as well looking here you can see
that the various description about the equals now you can see that it's using
mathematical terms like reflexive symmetric and transitive and then
explain what it means by them as you can see so reflex for any non null
reference value x.equals(x) should return true in that case if its symmetric for every
non-null reference values X&Y then x.equals(y) should return true if
only if y.equals(x) returns true so on and so forth and if you read those through
they actually makes sense and by that we can say for example pluto.equals
pluto passing pluto must return true and if earth equals terra is true
then of course terra.equals(earth) must also be true that's really what this sort of
saying here so the rules make sense and its just really a formal description of the
way we expect to equals to work anyway but it can be useful just if you wanna clear reference
of what we are trying to achieve in the equals method now there's a note as you can see
here that it's generally necessary to override the hash code method if equals
is overridden and we've talked about that before and we have seen what can happen if
that suggestion is not followed and you saw that our equals method in fact wasn't being
called until we implemented or overrode I should say the hash code method itself so
I'm going to finish this video here now in the next video what we're going to
do is we are going to come up with a mini challenge to challenge your
understanding of what has been taught in these last few videos and hopefully that
will help you understand things a little bit better so I'll see you in that next video