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 trial

Java Java Data Structures Organizing Data Interfaces

Walker Bolger
Walker Bolger
16,798 Points

How can you call "compareTo" when defining the method "compareTo"?

I have a couple of questions.

  1. When is "compareTo" being called? Is "Arrays.sort" calling it?

  2. 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?

Brian Bartholomew
Brian Bartholomew
1,741 Points

Answer 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 the Date object. For this example that is the case. However, Rob Bridges answers the first part of #2 very well.

9 Answers

Rob Bridges
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey 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
Brian Bartholomew
1,741 Points

Thanks 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
Joshua DeJong
3,138 Points

I 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
Walker Bolger
16,798 Points

Hi 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
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey 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
Walker Bolger
16,798 Points

Hi Rob.

That answers my questions. Thank you for your help!

Brian Bartholomew
Brian Bartholomew
1,741 Points

Hi 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
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey 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
Brian Bartholomew
1,741 Points

Hi 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
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Rob Bridges
Full Stack JavaScript Techdegree Graduate 35,467 Points

Hey 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
Juraj Sallai
7,188 Points

Sorry 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.

stackoverflow

@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) {