so continue on with the challenge our set challenge now I've mentioned at the end
of the previous video that their could potentially be a problem with our solar
system map
or I talk about it their being a map issue and the issue is with the solar system because if
we have a look and see how that is actually defined what we're doing is defining it
purely with the name of the body a string and there is no way to cater
for the Body type and obviously because we're using a map we only got the
concept of a key and the values so how do we get around that well its actually very
common problem when attempting to store and retrieve more complex objects
whether using one of the collection classes or a database for that matter
and there are many solutions to this problem
now databases allow records to be selected on several fields so it is
possible to make a primary key that consists of all the fields that uniquely defined
each record now another instance or another approach is creating unique
serial numbers for each record such a social security number for
people in the USA National Insurance numbers in the UK and text phone numbers
in Australia and one drawback of this approach is that you couldn't retrieve
if someone's record from a map unless you actually know their serial number now most
objects that have been discovered in the universe interestingly
enough are given a serial number by the
International Astronomical Union that's these guys I'll just that on the
screen out of interest these guts actually assign that unique serial number
effectively for every object that actually found in the universe so what
we could do we could replace our string with that but that also has got
disadvantages and the big one is that the number of course must be know in
order to retrieve the appropriate entity or
entry from the map so in this specific example that will probably be
the best option but these examples and challenges is designed to demonstrate
techniques that can be used in many different applications so if you have
added an IAU number field to the class the International Astronomical Union and used
that and that is a perfectly valid solution so in other words you would
change referencing the name and refer instead to the IAU field use that in your look ups
and obviously have that in your heavenly body summary as well so your linking
it back to that that's a valid solution you may also concatenated the name and body
type[ to create strings such as Pluto planet and planet dwarf_planet
and those type of things that would also be fine because that's covering both the
name and also the body type as well but for my solution what I'm gonna do is
create a class a key class and give the heavenly body class a field of type key
because this key is gonna be closely tied to the heavenly body class I'm
gonna make it a static inner class of the heavenly body class
so lets go and that I'm going to heavenly body and come down and put it within the class so
its going to be.....
.....
...we are going to create a getter for both of them Im in the
wrong place it should be there so.....
.....so we're going to override that....override both our equals
and our hash code so...and we'll come back to hash code in a minute will
actually do the equals first we're going to start off...
.....
...we need to also check the body type and we saw this first in the previous video so...
..so we are doing a check their so if name matches then we also do
a search and return the results of comparing this.bodytype to key.getbodytype
so obviously that returns true we know that there is a match
otherwise returns false....so. that's our equals method and the hash code we are going to do
very similar to what we did in fact the same as we did so we could copy some
of this code but will just type it again.....
.....so as you can see the
key class is very simple and gives a way to deal with a combination of name and body type in
a single object because we're gonna be using the key in a map that's why we've
needed to override equals and hashCode methods and as you saw when I typed it
pretty much identical to the methods that we previously just overrode in heavenly body
itself generally speaking it's a bad idea to have to duplicated code like
this but we can fix that by making heavenly body methods just call the method
in our new key class and the equals method still needs to check that the
object being compared is a heavenly body and must cast to a heavenly body type in
order to access as a key so lets do that so go back to the
equals method for heavenly body not within the inner class that we just
created this one here were going back to the equals within the heavenly body
class itself so you saw the code on line 54 can stay the same if
this equals equals object return true so if we're trying to compare the exact
same object in memory we know that that's ok we do not need to do any other
checking but will change this a little bit will still leave the test in there for checking to
see whether the object instance of heavenly body when we create our reference
here heavenly body object the object equals heavenly body objects so we need that then what
we're going to do their is that is going to take this code out here because we are going to use the key code
...now we got an error their and we are
expecting that error because we haven't actually added the key field to the
heavenly body class the key object is gonna be effectively going to be
field which is our key so we have to do that and the error will go away once we done that and
the heavenly bodies hash code is actually in simpler as a result of that because what we want
to do is get rid of all of this and just make it literally return the contents
so its gonna be.......and we are getting the error because we haven't added the key to the heavenly body class so
what we can now do is replace the 2 key fields name and body type with a key so I'm coming up here
to the top of heavenly body and where we've got name and body type we can delete those
....instead we put.....we need to also initialize
a constructor to get rid of that error so we need to get rid of the
other 2 field that we previously had that we have now deletes and.....
....and even though we've defined this as a private
constructor on line 78 that works because this is an inner class to
our heavenly body and that's where we were instantiated on line 24 in the public
constructor the heavenly body and we need to remove some of those methods the getter
for name and body type because they aren't in their anymore we also need to add a getter and its gonna be there for
our key.....
....and if we go down and check and the other thing we need to change is
the toString and can do that a little bit different we can.....
....to get that to work now the other thing we need to do is we need to
add
the method or a method to make a key so the actual implementation of the keys
is not something that uses of the class should have to know about but in order
to retrieve a heavenly body from the map we need a key when all we
really have is a name and a body type so in other words what we want to do is pass
and a name and body type and have a method return the valid key which is gonna
be use to look up an entry in our map effectively so what we
gonna do to do that we're going to add that here so going to make that method
public static....
I'm making it static so that the key can be obtained without an instance of heavenly body to
call the method on so public static....
......and again
they can then use what we return that key object and they can use that to then
lookups in the map object and we change to string so we shouldn't have any errors
and if we went back to equals the equals method is now working you can see on line 55
return this.key.equals this is the equals method that's used in heavenly
body and also the hash code is now this.key because we've got the key field
their as well that's working nicely ok so we've now finished making our changes so
what we need to do is go back to main and first things first we need to add or
change our new map because at the moment you can see on line 9 its got
a string and a heavenly body what we want to do is make the key no longer be
a string but we want it to be the actual key objective that we created so we can have that
as....and obviously we need to change some code
as well and what we need to do we got all these references to temp.getName
we wanna change all of those instead of getting the name to actually
get the actual key instead so what we're going to do is copy those and we're going to
do a search and replace
...temp.getName and we're going to fix that with temp.getKey and will do a
replace all and we got tempMoon.getname so we are gonna do the same thing....and replace that with....
...ok so we still got some errors here plane.getName we can do the same again we just
making these changes.... and again
because we removed the name and the body type and replace it with the key
we need to change all those entries body.getName is another one so......
...we are going to replace that as well....we
must be getting down to most of these errors now ok and to go back and check if you have look in our
key the other thing is because we are referencing key what we haven't done yet is we haven't added
a toSting to that so we should really add a toString to that method at the moment we only got
the toString which is in the heavenly body but we really need one in the keys
as well if we are gonna be referencing that so what we can do is come down here and override to
string....
so if we are referencing just the key we got a to string that returns just those two items
and of course in the heavenly body the toString is the name the body type and
the orbital period but they are because they are different objects now the other
thing here is we need to start checking these warnings because if we come down here on this line
here on line 82 we've clearly got a problem here and it's because we trying
to access the object using the name and now we are obviously using key so we need to change
that so that we can actually pass that parameter and get back a key because
clearly that's not gonna work anymore that now that we replace the keys
which was originally a string we've now replace that with a key object what we need to
do is use our make key method for that very reason so we know its mars so we can change
that two heavenly body.....remember its a static method so that we can call this
without having instance of the heavenly body so.....
....
....now that's got a valid call their and another one down here that just giving us a
different message basically its saying we can replace it with a for each call so we can leave
that that's no problems for now so if we run this we should get the code all working without
errors and our previous tests should still work and I need to make a change their and that should be.....
.....because obviously we've now got a key object so that will
fixed that up so run it again
ok so w should have everything working like it was before you can see we got
the Pluto is now appearing twice as we change the body type
planet to dwarf planet we still got our trues and false and everything else looks
good there we got all our planets moons of Mars and then obviously all the moons in our solar
system all the ones that we've actually defined in the code so we are now ready to
test the test cases 4 and 6 and just going back to our code again
.....
remember 4 we are attempting to add a duplicate to a map results in the original
being replaced by a new object and number 6 2 bodies with the same name but different
designations can be added to the same map and can be retrieved from the maps so we're
ready to test those now so lets go back to main so lets do test 6 first
so we can do solar system......
......
...and we need do the same thing but with our other entry which of course was Pluto with a dwarf
planet
so we change that to the body type......we should be able to confirm that
they're both in their so lets check whether we get the output from both which will
confirm basically test six is working and you can see there from the map the
last two printouts Pluto planet and 248 is the orbital period and Pluto dwarf planet
so that's clearly working and the last one test case 4 we can check that by
changing the new Pluto back to a planet remember we added this new dwarf planet so if we
change that and make that just a planet again and we want to do is check the planet
Pluto so it should have an orbital period of 842 because that's the new
one bearing in mind that what we wanted to do was replaced that that was part of
the challenge if it there was a duplicate so if we do that and run it you can see
that Pluto planet 842 so it has updated it and the second entry is now null
because it's no longer a dwarf planet and that's what we are expecting it to actually
do alright so we are basically done let's just add one final bit of code because I know this
video is becoming an epic again we can just as a final check print out the entire
solar system map so lets do that so make a bit of space and put....
......
...remember we got a toSting so that will work just fine....
....and lets just run that
and their you can see that we've got the various moons and planets and so forth
that's all working nicely and just to be complete lets just change this back to a dwarf
planet just to be sure that we can actually see that in our final run and we now got our
two plants back again so that's it that's the set challenge I hope that you got a lot of of that
and you enjoyed your version of creating a solution to this
so I'm going to end this video here and I'll see you in the next video