• Post Reply Bookmark Topic Watch Topic
  • New Topic

help with compareTo method  RSS feed

 
William Pen
Greenhorn
Posts: 7
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to write a method that compares two circle's areas
public int compareTo (Circle other)

I would call it from the main method with circleA.comparedTo(circleB) , but I don't understand how I can compare two circles when there is only one parameter for the compareTo method, and also create circleA in the main method.

Thanks for reading and thanks in advance for help
 
William Pen
Greenhorn
Posts: 7
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nevermind, I figured it out.
 
Jeanne Boyarsky
author & internet detective
Marshal
Posts: 37181
515
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Glad you solved the problem. Want to share what you learned for the next person reading this?
 
Campbell Ritchie
Sheriff
Posts: 55351
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

As well as explaining how you solved the problem, explain whether you were trying to implement this interface.
 
William Pen
Greenhorn
Posts: 7
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
^ Yes, I was trying implement that

To the next person reading this:

You can compare two objects in a method with only one parameter by using "this."
this refers to the object that the method was called upon.
In this case this refers to circleA from circleA.compareTo(circleB)

Ex:
public double compareTo (Cirlce other) {
    int value  =2;
    double r1 = this.getRadius( );
    double r2 = other.getRadius( );
    if (this.area(r1) < other.area(r2))
      value = -1;

//rest of method
}



 
Henry Wong
author
Sheriff
Posts: 23282
125
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
William Pen wrote:
To the next person reading this:


Thanks for following up. You earned a cow.

Henry
 
Junilu Lacar
Sheriff
Posts: 10950
158
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
William Pen wrote:
You can compare two objects in a method with only one parameter by using "this."
this refers to the object that the method was called upon.
In this case this refers to circleA from circleA.compareTo(circleB)

Ex:
public double compareTo (Cirlce other) {
    int value  =2;
    double r1 = this.getRadius( );
    double r2 = other.getRadius( );
    if (this.area(r1) < other.area(r2))
      value = -1;

//rest of method
}

A few things wrong about your example:

1. compareTo() should return an int; your example declares a double return value.

2. There's really no need for the value local variable nor is there a need for the r1 and r2 variables.

3. The area() method depicted doesn't make sense - why would you need to pass in the radius if the radius is already a field of a Circle object?

4. I would imagine a better implementation of Circle.compareTo() would be something like this:

 
Junilu Lacar
Sheriff
Posts: 10950
158
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I might also argue that if a Circle has an immutable radius property, then its compareTo() method only needs to check that field.

 
Tobias Bachert
Ranch Foreman
Posts: 85
18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Small sidenote: Double.compare(radius, other.radius) is preferable as it does the same without creating the intermediate Double instances. (Additionally the wrapper constructors will most likely be deprecated in Java9.)
 
Junilu Lacar
Sheriff
Posts: 10950
158
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tobias Bachert wrote:Small sidenote: Double.compare(radius, other.radius) is preferable as it does the same without creating the intermediate Double instances. (Additionally the wrapper constructors will most likely be deprecated in Java9.)


Good point.
 
Campbell Ritchie
Sheriff
Posts: 55351
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . if a Circle has an immutable radius property . . .
I was hoping yesterday that somebody would notice that. That sort of thing varies from object to object, but if we are going into the realms of geometry. A circle (small c) has a radius, a diameter, a perimeter (=circumference) and an area. The diameter is 2r, the circumference is 2πr and the area is πr². That means that all of them are derived from the radius, and also that they all increase monotonically with the radius. So you only need to compare radii, because if the radius is bigger, then diameter circumference and area are also bigger. Also they all have the property that they are > 0.
If and only if the radius is denominated as an int, you can implement the Circle class like this:-If you look in the Java™ Tutorials, you will find there are all sorts of pitfalls if you use − because of the risk of overflow. But overflow won't occur if you subtract two ints with the same sign. If you allow negative numbers in as radii, you can get all sorts of horrible errors.
 
Campbell Ritchie
Sheriff
Posts: 55351
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tobias Bachert wrote:. . . Additionally the wrapper constructors will most likely be deprecated in Java9.
It would appear from this API link that is correct. They are obviously moving from constructors to factory methods, as in this and other date‑time classes.

I had to learn to use new Integer(123) for entering numbers into Lists; that was before generics, and before the Integer#valueOf(int) method was introduced.
 
Stephan van Hulst
Saloon Keeper
Posts: 7737
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To implement the compareTo() method easily when the object has fields that can have negative values, I like to use a Comparator:
 
Campbell Ritchie
Sheriff
Posts: 55351
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A few hours ago, I wrote:. . . you can implement the Circle class like this:-. . .
That would have been better asStephan: I like the Comparator with the λ and the method reference; maybe you would like to explain it a bit more fully, since this is the Beginning forum and many people won't be familiar with the concept.
 
Stephan van Hulst
Saloon Keeper
Posts: 7737
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sure.

Two temperatures can be compared by comparing the internal normalized representation, which in this case is the number of degrees Celsius as a double field. We could perform this comparison ourselves by using relational operators, or we could use a Comparator that already knows how to compare two double values naturally. Comparator.comparingDouble(ToDoubleFunction<T> keyExtractor) returns a Comparator that uses the keyExtractor argument to convert an object to a double value, and then compares two objects by comparing the double values they were converted to.

Because ToDoubleFunction<Temperature> is a functional interface, we can pass a lambda expression to the comparingDouble() method. This lambda expression tells the comparingDouble() method how to convert a Temperature to a double value. It looks like this:

However, when you use a lambda expression that declares a variable, and all you do is call an instance method on that variable, a cleaner way to do this is pass a method reference:

In this context, Temperature::degreesCelsius essentially means: "Take the degreesCelsius() method of the Temperature class, and use it as a function that can convert a Temperature to a double.

So, we now have a Comparator that can compare two Temperature instances by comparing the double values from calling their degreesCelsius() method. The actual comparison would happen by passing the two instances to the compare() method of the Comparator:

However, what would happen if we passed a null reference to Temperature.compareTo()? Our Comparator would then fail with a NullPointerException. We still need to tell it what to do when it encounters null. Comparator.nullsFirst() takes a Comparator and returns a new one that performs exactly the same comparison, except it sorts null references before non-null references. The final result is:
 
Stephan van Hulst
Saloon Keeper
Posts: 7737
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If we didn't use a Comparator, the code would look like this:

As you can see, the approach using the Comparator is much more declarative and concise.
 
Tobias Bachert
Ranch Foreman
Posts: 85
18
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would omit the #nullFirst/null-check as Comparable#compareTo specifies to throw a NullPointerException for null arguments.
The alternative compareTo method will fail iff either value is NaN; using the #compare method of the wrapper type avoids possible bugs introduced by forgetting over-/underflow or NaN. In my opinion the comparator based approach should be compared to

I agree that the comparator approach may be better readable iff there is more than one value to compare as each value has to be specified only once instead of twice (but would still use Wrapper#compare/manually written comparison if performance is relevant).
vs.
 
Stephan van Hulst
Saloon Keeper
Posts: 7737
142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah my bad, I've been working in .NET a lot lately, and you're free to deal with null any way you want in the CompareTo() method.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!