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 - Retired Organizing Data Interfaces

Matt O'Connor
Matt O'Connor
1,705 Points

Struggling to understand various concepts in this lecture

Despite scanning through the other questions I'm struggling with quite a few concepts in this lecture. It may seem like I didn't watch it but I assure you I did and am still completely bamboozled!

Why are we casting an 'Object' object to a 'Treet' object?

public int compareTo (Object obj) {
    Treet other = (Treet) obj;

if the compareTo method accepts an object as a parameter couldn't we just use (Treet other) in the method signature?

I don't understand the following statement...

if (equals(other)) {
    return 0;
}

I assume we are using equals and not someObject.equals because we are referring to the class itself. We are comparing the object itself with the passed in object which was then cast to 'other'? How can it do this comparison? What is it comparing? I understand the return 0 if when an object is equal to another object (?)

Need a similar explanation for the next bit of code...

int dateCmp = mDate.compareTo(other.mDate);
if (dateCmp == 0) {
    return mDescription.compareTo(other.mDescription);
}

Now I'm really confused! In the previous java course I understood calling a method within a method but I don't understand the implementation here.

Finally...

for (Treet exampleTreet : treets) {
    System.out.println(exampleTreet);
}

I understand that having a toString method will print out a string of the specified format if you sysout the object, but don't understand how this piece of code above has automatically implemented the compareTo() method without us actually referring to it.

Is compareTo() ran through each iteration of the loop? if so can someone guide me as to what is happening in each iteration.

Hoping someone might be able to help unscramble this for me! Thanks

3 Answers

1st question: Why do we have to cast obj to a Tweet?

public int compareTo (Object obj) {
    Treet other = (Treet) obj;

Answer: because, at compile time, obj is an Object, not a Tweet. In the method Craig uses two properties with other: mCreationDate and mDescription. other, since it is a Tweet, has these properties. obj, since it is an Object, does not have these properties. So without the cast you'd get a compiler error.

2nd question: What is being compared here?

if (equals(other)) {
    return 0;
}

Answer: this is short hand for this.equals(other), where this means "me", the current object (as you surmised). As lamda points out, you can avoid this if your class implements Comparable<E> rather than Comparable, i.e., uses generics. Because then the compiler will require that the parameter for compareTo() be E, rather than Object. E.g., if the Tweet class implements Comparable<Tweet> then compareTo(Tweet t) would be required, with no casting. One nice thing about doing it with generics is that Craig's method will throw an exception if it's passed anything other than a Tweet, while compareTo(Tweet t) won't because it can't be given anything other than a Tweet.

3rd question: what's going on here:

int dateCmp = mDate.compareTo(other.mDate);
if (dateCmp == 0) {
    return mDescription.compareTo(other.mDescription);
}

Answer: the first line assigns an int named dateCmp a value, the result of comparing this.mDate to other.mDate. Then, in the second line, it says that if the int is 0, return the result of another comparison. (As you may remember, any compareTo() method has to return either a positive integer, a 0, or a negative integer.) So, what's happening here is that if the dates are equal, then the decision which is "before" is made based on the descriptions. For a different example, say you were comparing date objects that have just month and day properties. Then, for 4/4 and 4/11, since the months are equal, a compareTo() would return 0, and then you'd look at the days, and return a -1 since 4 is "before" 11.

4th question: "I understand that having a toString() method will print out a string of the specified format if you sysout the object, but don't understand how this piece of code above has automatically implemented the compareTo() method without us actually referring to it."

for (Treet exampleTreet : treets) {
    System.out.println(exampleTreet);
}

There's nothing about compareTo() here. System.out.print(), if given an object, will call the toString() method on that object. If the method has been overridden, then it will print whatever the method tells it to (as Craig does at 12:15, by adding mCreationDate). If not, then it will use the method inherited from Object and print something like Tweet@FE26B45..., i.e., the class and memory address.

Happy coding!

Matt O'Connor
Matt O'Connor
1,705 Points

Thanks for this. I'm slowly understanding the code but broadly speaking am still confused about how the sorting is performed.

(Just realised I'm using mDate in my code whereas Craig uses mCreationDate which makes things a little more confusing, apologies)

Just to recap...

  • compareTo () method is the only method in the Comparable interface
  • We implement Comparable and therefore have to implement all methods from Comparable, which would just be compareTo ()
  • compareTo only accepts an 'Object' argument, hence needing to cast to a Treet
  • compareTo () returns 0 if 'something' is equal to 'something else', negative integer if 'something' is less than 'something else' and a positive integer if 'something' is greater than 'something else'

After that is where I'm still shaky...

  • Are we override compareTo() and define our own logic in choosing what to return? (I understand we have to override compareTo() if we implement the interface)
  • if (equals(other)) is used to compare 'this' object with the 'other' object but what are we specifically comparing at this stage? How can an object that has various methods and variables be compared to another object? At the moment my brain is only able to understand comparing 'something', like ints, Strings etc.
  • In this statement -int dateCmp = mDate.compareTo(other.mDate); we are comparing the date from 'this' object with the date from the 'other' object and storing the result (will this be -1, 0 or 1?) in dateCmp. (?)
  • We then check to see whether dateCmp is = 0, i.e. the dates between tweets match, and in this case comparing the description instead.

Let's say there are 4 tweets can anyone help me understand how this method achieves organizing those 4 tweets? How many times is the method invoked? At each time the method is invoked what actually is being passed into the compareTo method?

I have to concede to getting a little flustered by this. Everything up to this point in the course and the previous course I was able to follow but this lecture feels like the difficulty has been cranked up.

Many thanks,

Stephen Shine
Stephen Shine
5,991 Points

Thanks for that! It's cleared up quite a few questions that I had about the toString method.

Am I right in saying that a similar reasoning applies to the compareTo method? compareTo is part of the Arrays.sort. So when we type:

Arrays.sort(treets);

We're implementing our version of compareTo, which first compares the dates of objects, then goes on to compare the descriptions if the dates are the same?

public int compareTo (Object obj) {
    Treet other = (Treet) obj;
Why are we casting an 'Object' object to a 'Treet' object?
if the compareTo method accepts an object as a parameter couldn't we just use (Treet other) in the method signature?

I was wondering the same thing and it gets clarified in a later video (topic: Generics). I believe you have to use "Object" and can't use "Treet" because when you are overriding the inherited compareTo() method, it always expects "Object" type. If you try to replace it, you'll get a compiler error. Try changing "Object" to "Treet" and removing the cast.

Regarding your question about equals. By default, all Objects have an equals() that checks to see if they are the same object and it is using that. On a later video, you will write your own equals() method in Treet.java.

Regarding your question about for( ... ){ ... }

for (Treet exampleTreet : treets) {
  //System.out.println(exampleTreet);
  // the above line is equivalent to:
  System.out.println(exampleTreet.toString());
  // All Objects (including Treet) inherits toString() from the main Object class
}
Matt O'Connor
Matt O'Connor
1,705 Points

Still struggling with this one, particularly understanding the recursive nature of the method. I have looked at other similar answers but I didn't understand them.

  • Does an implementation of the compareTo() method have to include all of -1, 0 and 1 as return statements?
  • How is if(equals(other)) performed? What part of the objects are being compared?
  • Once we return our value from the compareTo() method, what is done with that value that then organizes the treets? I understand the value refers to less than, equal to or greater than, but how do we use that value to move the treets in the array to the ordered position.
  • Looking at the API is it this sort method we are implementing from Arrays? public static void sort(Object[] a)
  • Is the compareTo method used in mCreationDate.compareTo(other.mCreationDate) referencing this.compareTo() or date.compareTo?

I don't suppose anyone is available to step through the code with me in real time outside the forums? I can leave a Skype if someone is willing to help a brother out!

Thanks,

1st question: properly done, compareTo() must return a 0 if the objects (here Tweets) are the same, a negative number (not necessarily -1) if this comes before, or "is less than", the other, and a positive number if this comes after.

2nd question: it depends on how you write the compareTo() method. For a Point class, you would probably compare the x and y coordinates. For a Date class you would probably compare years, then months, then days. For a Student class you would probably compare names, then birthdates, etc. It's up to you. Take the Point class, you could compare x coordinates, or y coordinates, or both, or the distance of the points from the origin, etc. Your choice, depending on how you want point objects sorted.

3rd question: basically Java will use your compareTo() to sort the Tweets, based on the way you write the compareTo() method in the Tweet class.

4th: to sort an array you use Arrays.sort(arrayName)

5th: I haven't watched the video recently, but it looks like the code is using the compareTo() of the Date object.

Re your point that compareTo() must accept an Object. That depends. If the Tweet class implements Comparable, then yes, it has to be compareTo(Object o). But if it implements a generic, say, Tweet class implements Comparable<Tweet>, then no, it has to be compareTo(Tweet t).