Implementing the compareTo method

P

Paul Morrison

Hi,

I have written an Edge class that takes two Point values as parameters and I
want to make the class implement comparable but I dont know how to do it.
This is what I have got so far:

public class Edge implements Comparable<Edge> {
Point point1;
Point point2;
double ymin, ymax, xvalue, oneoverm;

Edge(Point point1, Point point2) {
this.point1 = point1;
this.point2 = point2;
.......
public Edge compareTo(Edge e) {
//to do
}

I want to sort the edges in order of their ymin values, would I be correct
in thinking that I do something along the lines of:

if (edge.ymin < e.ymin)
return edge;
else
return e;

Is this on the right lines?

Cheers

Paul
 
J

James Westby

Paul said:
Hi,

I have written an Edge class that takes two Point values as parameters and I
want to make the class implement comparable but I dont know how to do it.
This is what I have got so far:

public class Edge implements Comparable<Edge> {
Point point1;
Point point2;
double ymin, ymax, xvalue, oneoverm;

Edge(Point point1, Point point2) {
this.point1 = point1;
this.point2 = point2;
.......
public Edge compareTo(Edge e) {
//to do
}

I want to sort the edges in order of their ymin values, would I be correct
in thinking that I do something along the lines of:

if (edge.ymin < e.ymin)
return edge;
else
return e;

Is this on the right lines?

Cheers

Paul
Yeah that's the idea, but you want to use the instance variables of the
object somewhere, so your edge.ymin should probably be this.ymin.

James
 
P

Paul Morrison

public Edge compareTo(Edge e) {
Yeah that's the idea, but you want to use the instance variables of the
object somewhere, so your edge.ymin should probably be this.ymin.

I have just looked, and it seems that the return type of compareTo has to be
int. What exactly do I return?

Paul
 
J

James Westby

Paul said:
I have just looked, and it seems that the return type of compareTo has to be
int. What exactly do I return?

Paul
Ah yes, sorry, the Javadoc states

'Returns a negative integer, zero, or a positive integer as this object
is less than, equal to, or greater than the specified object.'

so

if this.ymin < e.min return -1
else if this.ymin > e.min return 1
else return 0

The other thing to note is that it is defined as compareTo(Object o), so
you want to make a cast from the parameter first. The method is defined
to throw a ClassCastException if the type is not correct.

See http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Comparable.html
for more info

Also as ymin is a double you shouldn't expect this method to return 0,
but it might in some cases.

James



James
 
P

Paul Morrison

I will expand on what I am doing as there may be an easier way to do this. I
have an ArrayList which holds ArrayLists of 4 numbers. I want the sort the
second ArrayList in order of the first item in that ArrayList, going from
lowest to highest.

I.e.

ArrayList -> ArrayList -> ymin
ymax
xvalue
1/m

I was looking at writing a loop, going through each ArrayList and comparing
the first element of each, each time keeping the minimum one, but I feel
that this will be inefficient.

Hope this makes things clearer.

Paul
 
Z

zero

I have just looked, and it seems that the return type of compareTo has
to be int. What exactly do I return?

Paul

if edge1 is "smaller" than edge2, return a negative value
if edge1 and edge2 are equal, return 0
if edge1 is "greater" than edge2, return a positive value

The exact value depends solely on your implementation. A possible
implementation could be:

final double PRECISION = 100.0;

return (int)((e.ymin - this.ymin) * PRECISION);

Here you can use PRECISION to manipulate the precision of the comparison.
This may be necessary if you're comparing values that are close to
eachother.
 
J

James Westby

Paul said:
I will expand on what I am doing as there may be an easier way to do this. I
have an ArrayList which holds ArrayLists of 4 numbers. I want the sort the
second ArrayList in order of the first item in that ArrayList, going from
lowest to highest.

I.e.

ArrayList -> ArrayList -> ymin
ymax
xvalue
1/m

I was looking at writing a loop, going through each ArrayList and comparing
the first element of each, each time keeping the minimum one, but I feel
that this will be inefficient.

Hope this makes things clearer.

Paul

Can i ask why you are using an ArrayList to store those four numbers? Is
it always four numbers?

James
 
P

Paul Morrison

Can i ask why you are using an ArrayList to store those four numbers? Is
it always four numbers?

Yes it is always four numbers. I am using an ArrayList rather than an array
as I am more comfortable with these, not for any other reason. Would it be
easier to do this with another Collection type?

Paul

PS Sorry for replying directly, wrong button!
 
G

Googmeister

James said:
The other thing to note is that it is defined as compareTo(Object o), so
you want to make a cast from the parameter first. The method is defined
to throw a ClassCastException if the type is not correct.

Or you can use generics as the OP does and avoid the cast.
Also as ymin is a double you shouldn't expect this method to return 0,
but it might in some cases.

You should absolutely expect this method to return 0 in some cases,
e.g., e.compareTo(e).
 
G

Googmeister

zero said:
if edge1 is "smaller" than edge2, return a negative value
if edge1 and edge2 are equal, return 0
if edge1 is "greater" than edge2, return a positive value

The exact value depends solely on your implementation. A possible
implementation could be:

final double PRECISION = 100.0;

return (int)((e.ymin - this.ymin) * PRECISION);

Here you can use PRECISION to manipulate the precision of the comparison.
This may be necessary if you're comparing values that are close to
eachother.

Don't do these floating point hacks - you'll break the transitivity
part of the compareTo() contract.
 
J

James Westby

Paul said:
Yes it is always four numbers. I am using an ArrayList rather than an array
as I am more comfortable with these, not for any other reason. Would it be
easier to do this with another Collection type?

Paul

PS Sorry for replying directly, wrong button!

Well there's nothing wrong with it, but one use Collections is when you
don't know how many elements there are ahead of time.

You could use an ArrayList of objects that you define, implement
Comparable on these objects, then use Colections.sort, but then again an
object to hold four numbers may be a bit much. The natural way would be
to use arrays.

To do it your way have a look at this, the code needs tidying up to deal
with cases where you don't get exactly what you want, but this runs and
shows the concept. It's a JUnit test case, but you could wrap it all in
a main() instead if you wanted. The key is the Comparator that
Collections.sort allows you to provide. Also it will be a lot neater if
you are using 1.5 (which I think you are).

James



import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import junit.framework.TestCase;

/**
* @author jw2328
*
*/
public class ArrayListTest extends TestCase {

public void testNothing() {

List a = new ArrayList();

List b = new ArrayList();

b.add(new Integer(1));
b.add(new Integer(2));

List c = new ArrayList();

c.add(new Integer(3));
c.add(new Integer(4));

a.add(c);
a.add(b);

Iterator it = a.iterator();

while (it.hasNext()) {
System.out.println(((ArrayList) it.next()).get(0));
}

Collections.sort(a, new Comparator() {

public int compare(Object o1, Object o2) {
Integer a = (Integer) ((ArrayList) o1).get(0);
Integer b = (Integer) ((ArrayList) o2).get(0);
return a.compareTo(b);
}
});

System.out.println("Sorted:");

it = a.iterator();

while (it.hasNext()) {
System.out.println(((ArrayList) it.next()).get(0));
}

}

}
 
O

Oliver Wong

Paul Morrison said:
Yes it is always four numbers. I am using an ArrayList rather than an
array
as I am more comfortable with these, not for any other reason. Would it be
easier to do this with another Collection type?

You might want to define a class to encapsulate these for values. For
example:

<code>
class Edge implements Comparable<Edge> {
double yMin, yMax, xValue, inverseM;

/*Implement the compareTo method here*/
}

ArrayList<Edge> myFoos = new ArrayList<Edge>();
</code>

- Oliver
 
J

James Westby

Googmeister said:
James Westby wrote:




Or you can use generics as the OP does and avoid the cast.




You should absolutely expect this method to return 0 in some cases,
e.g., e.compareTo(e).


Absolutely, sorry, when I wrote this I thought I had phrased it badly,
and I obviously did. What i meant was that his code shouldn't rely on
e.compareTo(f) == 0 for some e != f. I should have been more specific,
thanks for pointing it out.
 
P

Paul Morrison

You might want to define a class to encapsulate these for values. For
example:

<code>
class Edge implements Comparable<Edge> {
double yMin, yMax, xValue, inverseM;

/*Implement the compareTo method here*/
}

ArrayList<Edge> myFoos = new ArrayList<Edge>();
</code>

I have done the final part, ie adding <Edge> to my initialisation of the
ArrayList, but when I call, for example, myFoos.add(...) I get an error when
compiling:

cannot find symbol method(java.util.ArrayList)

Any idea why this would happen? It compiled before I changed it. Could it be
that I initialise the ArrayList before I create the Edge class?

Paul
 
O

Oliver Wong

Paul Morrison said:
I have done the final part, ie adding <Edge> to my initialisation of the
ArrayList, but when I call, for example, myFoos.add(...) I get an error
when compiling:

cannot find symbol method(java.util.ArrayList)

Any idea why this would happen? It compiled before I changed it. Could it
be that I initialise the ArrayList before I create the Edge class?

I don't know why you are getting this error. This code compiles find for
me:

<SSCCE>
import java.util.ArrayList;

public class Edge implements Comparable<Edge> {

double yMin, yMax, xValue, inverseM;

public int compareTo(Edge arg0) {
if (this.yMin < arg0.yMin) {
return -1;
}
if (this.yMin > arg0.yMin) {
return 1;
}
return 0;
}

public static void main(String args[]) {
ArrayList<Edge> myFoos = new ArrayList<Edge>();
myFoos.add(new Edge());
}
}
</SSCCE>

- Oliver
 
R

Roedy Green

Yes it is always four numbers. I am using an ArrayList rather than an array
as I am more comfortable with these, not for any other reason. Would it be
easier to do this with another Collection type?

for a fixed known number of elements, an array is the way to fly. They
are much faster and the type safety is not nearly so flaky.
 
R

Raymond DeCampo

Roedy said:
for a fixed known number of elements, an array is the way to fly. They
are much faster and the type safety is not nearly so flaky.

....and you can use Arrays.asList() for interoperability with collections.

HTH,
Ray
 
P

Paul Morrison

I have written an Edge class that takes two Point values as parameters and
I want to make the class implement comparable but I dont know how to do
it. This is what I have got so far:

OK, I have written a compareTo method as follows:

public int compareTo(Edge e) {
if (this.ymin < e.ymin)
return -1;
else if (this.ymin > e.ymin)
return 1;
else
return 0;
}

I then try to sort an ArrayList of Edges by calling:

edgeTable.sort();

but I get the error:

C:\AETFillAlgorithm.java:73: cannot find symbol
symbol : method sort()
location: class java.util.ArrayList
edgeTable.sort();

I thought that once I had written the compareTo method I would be able to
sort an ArrayList of type Edge. Is there more that I must do?

Paul
 
J

James Westby

Paul said:
OK, I have written a compareTo method as follows:

public int compareTo(Edge e) {
if (this.ymin < e.ymin)
return -1;
else if (this.ymin > e.ymin)
return 1;
else
return 0;
}

I then try to sort an ArrayList of Edges by calling:

edgeTable.sort();

but I get the error:

C:\AETFillAlgorithm.java:73: cannot find symbol
symbol : method sort()
location: class java.util.ArrayList
edgeTable.sort();

I thought that once I had written the compareTo method I would be able to
sort an ArrayList of type Edge. Is there more that I must do?

Paul


If you look there is no sort method on ArrayList, you must use

Collections.sort(edgeTable);

This will then use your compareTo method to do the sort.

James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top