Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialWalker Bolger
16,798 PointsHow can you call "compareTo" when defining the method "compareTo"?
I have a couple of questions.
When is "compareTo" being called? Is "Arrays.sort" calling it?
How can we call "compareTo" when defining "compareTo"? Is this because the "compareTo" we are defining uses an object as a parameter while the "compareTo" that we are using to compare creation dates uses a date as a parameter?
9 Answers
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 PointsHey there Walker,
Yes the method is being called when we call Arrays.sort(treets); we had to implement comparable because Treets did not have a any way to compare them prior to that, so we have to use our @Override code to set them up to be compared by their creation date.
If we hadn't overridden the regular method to compare the treets as you saw it would have given us the is not comparable error, which is what our sort methods requires to sort them, so we basically overrode what java referenced when trying to compare the object, which our treet class did not contain, and tell java to use the mCreationDate instead, this was all to make Array.sort(treets) not throw an error.
As far as a method calling itself this is indeed something that is acceptable in java, it is called recursion and basically it is when a fuction or method calls itself.
A popular once is to solve factorials in math.
Let's say we have a factorial 6!m this is basically 6 x 5 x 4 x 3 x 2 x 1.
if we wanted to write a method to solve these in java we could use recursion.
public int myFactorial(int n) {
if (n == 1) {
return 1; // factorial of 1, is always one.
}
else {
return n * myFactorial(n-1);
}
we are calling the method in the body of the code that defines the method, and yes this does work.
It also leads to a lot of bad jokes (You can't talk about recursion without first talking about recursion is a popular one)
Thanks, if this doesn't help let me know and I'll try again.
Brian Bartholomew
1,741 PointsThanks agian Rob Bridges,
If this is truly recursion then our Treet.compareTo(Treet other)
would have to accept a String
, Date
, or Treet
object. It does not do that. If you pass a Date
into our this.compareTo(Treet other)
method you will get
error: incompatible types:
Date cannot be converted to Treet
You said, "You are correct when we call this.mCreationDate.compareTto(other mCreationDate) we are calling the method that we just defined to sort the Treets,"
We are absolutely not calling the method we just defined. That would look like this
this.compareTo(other.mCreationDate)
not
this.mCreationDate.compareTo(other.mCreationDate)
If the latter were the case, then it would not compile and we would get the error I shared above.
Therefore, I can only conclude that when we call the mCreationDate.compareTo(other.mCreationDate)
we are calling the method defined on the Date object. There is also a compareTo()
on the String
object.
I believe you were referencing this line
int dateCmp = this.mCreationDate.compareTo(other.mCreationDate);
I am going to try to write what is being said here.
Hey Treet
, you have a Date
object called mCreationDate
. And your mCreationDate
has a method compareTo(Date anotherDate)
that is expecting a Date
object. I would like to pass you this other Treets mCreationDate
referenced as other.mCreationDate
that I have which is a Date
object. Then I am going to let the Date
object run its compareTo()
and return a value that I will assign to the int
called dateCmp
.
I am grateful for your answer and sharing the recursion example. It is an awesome tool. However, to use it to explain what is happening here is incorrect.
Rob, I do not mean any disrespect through this continuing educational discussion. I learn a lot through debate and showing how I understand things. If you have any sources to support your thesis I would love to read them.
Craig Dennis, would you mind just taking a peak at this? If I am wrong I would love a better explanation of what is going on. Rob seems to believe he is right and he probably is. He seems to have much more experience than I do and I don't want to be the source of confusion. The odds are I am wrong and I just don't understand.
Joshua DeJong
3,138 PointsI have to say that I think about this in exactly the same way that Brian Bartholomew does. Recursive calls to the overridden compareTo() method don't make sense in this context, since there is no decrementing function or base case that recursive functions require.
Walker Bolger
16,798 PointsHi Rob.
Thank you for the answer. Recursion makes sense. I seem to remember seeing it in other programming languages.
As a clarification, when we override "toCompare" we aren't completely overriding the method, we are just adding the ability to sort Treet objects. Do I understand that correctly?
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 PointsHey Walker,
You probably have, almost all modern programming languages support recursion. older versions of Fortran, Cobal or Basic would not, past that it's a pretty popular tactic in all object oriented languages.
As to your question, yes you are exactly correct. We are just overriding the compareTo method for the instance of Treet which is a subclass of the super class Object, but since the general compareTo method used on almost all objects does not work for Treet, we had to basically tell Java "Hey, we're going to do this differently than you should expect, here's how you sort this class"
We haven't changed the method at all as it would normally would on most Objects, just for the instance of our Treet class.
Sounds like you understand it pretty well.
Walker Bolger
16,798 PointsHi Rob.
That answers my questions. Thank you for your help!
Brian Bartholomew
1,741 PointsHi Walker Bolger ,
I am very new to java at the moment so I am not sure I am answering this correctly, but I wanted to point out a flaw in your question and to the answers that were spawned from it.
If I am wrong please correct me!
When you ask "How can we call 'compareTo' when defining 'compareTo'?"
I don't believe the answer is recursion as Rob Bridges suggested (although a very insightful answer). We are not really calling the same compareTo()
at all. We are calling the compareTo()
method on the Date
object to compare the dates and then calling the compareTo()
method that is defined on the String
object to compare the descriptions.
Just as we defined our own compareTo()
methods for the Treet
object the String
and Date
object both have their own compareTo()
methods defined to override the Comparable
compareTo()
method.
Again, I am new to java so if this incorrect lets please get this resolved.
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 PointsHey there Brian,
He definitely did mean the recursive function of compare to. I've linked the code that he had in question.
@Override
public int compareTo(Treet other) {
if (equals(other)) {
return 0;
}
int dateCmp = mCreationDate.compareTo(other.mCreationDate);
if (dateCmp == 0) {
return mDescription.compareTo(other.mDescription);
}
return dateCmp;
}
We call compareTo Twice in the same algorithm that we use to override it in.
Thanks, hope this clears this up, and don't ever hesitate to check up on anything.
Brian Bartholomew
1,741 PointsHi Rob Bridges,
Thanks for the reply. So just for clarification
String str = "string";
String str2 = "string2";
int stringCmp = str.compareTo(str2);
This str.compareTo(str2)
calls the compareTo()
method on the String
object correct?
If this is the case, wouldn't
mCreationDate.compareTo(other.mCreationDate)
call the compareTo()
method on the Date
object rather than calling the compare to method on the Treet
object?
I feel that your example of recursion with factorials is a correct example of recursion, but is functionally different than the code that you linked.
Another reason I have trouble following this is because java methods
have signatures. So...
public int compareTo(Treet other) {...}
is expecting a Treet
object.
And
mCreationDate.compareTo(other.mCreationDate);
is expecting a Date
object.
Therefore, because of the values we are passing in it would call a different function than the one we are defining. If we look at your first example of recursion, which is brilliant,
public int myFactorial(int n) {
...
return n * myFactorial(n-1);
...
}
we can see that we are passing the same Object Type
this would mean that recursion would happen because the method signature matches.
If this is not the case, please explain how Date.compareTo()
in this cases ends up calling Treet.compareTo()
and causes recursion to happen.
I come from a Javascript
(I know it is not an Object oriented language like java
.) world and this is how it works there. I know that the languages are different, but the behavior at this point is theoretically the same. I just want to make sure that some week old programer does not get confused by this. Because right now, after programing for over ten years, am very confused by what the videos have taught me and what you are saying.
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 PointsHey Brian,
I definately understand it's confusing and hard to get around at first. Java makes sense after you spend time with it, before then it's the awkward kid that has odd habits.
You are correct when we call this.mCreationDate.compareTto(other mCreationDate) we are calling the method that we just defined to sort the Treets, and you are also right it is also expecting a date object.
However we're comparing Treets with their internal date object that we gave it, for the most part because that's how we wanted to order our list.
Let's say our Treets had another variable mTitle which was a string and we decided that a better way to order our treets would be my title.
Then our ensuing code(parts taken out for clarity and to give the general idea)
@Override
public int compareTo(Treet other) {
if (equals(other)) {
return 0; // we return the same value if it's the same this would lead to bugs if people gave their Tweet the same title
}
String titleCompare = this.mTitle.compareTo(other.mTitle);
exct....
What we're doing there is we're still comparing treets together, however we're asking that it compares the treets based on their title, which is stored in the variable in mTitle, as I hinted at this would be a very good way, because the likelyhood of someone having the exact title is much more probable than someone creating the same treet at the very same second that other (likely, but on a small scale project like this, safe to assume we're okay using the date).
Essentially we are creating and calling the method at the same exact time, and teaching the compiler how to compare them based on our method.
Thanks I hope I've been able to clear this up a bit, if not shoot back.
Juraj Sallai
7,188 PointsSorry for digging in old topic, but this was definitely not a recursion. If it was recursion, it would never ends, because our overriden compareTo() does not specify when to return -1 and when to return 1.
Look what are we actaully returning - date.compareTo(other.date) - this is not THIS overriden compareTo() method. It is compareTo() which belongs to Date object. If you want to do recursion, it would simply be just compareTo(other);
I would recommend check following link and comment from John Bollinger.
@Override
public int compareTo(Object obj) {
Treet other = (Treet) obj;
if (this.equals(other)) {
return 0;
}
return date.compareTo(other.date);
}
And FYI, you cannot use following code. In this way, you are not really overriding compareTo() method, because it needs Object argument, not Treet.
@Override
public int compareTo(Treet obj) {
Brian Bartholomew
1,741 PointsBrian Bartholomew
1,741 PointsAnswer to #2 "...Is this because the "compareTo" we are defining uses an object as a parameter while the "compareTo" that we are using to compare creation dates uses a date as a parameter?" is, yes, it calls the
compareTo()
on theDate
object. For this example that is the case. However, Rob Bridges answers the first part of #2 very well.