Java Forum / General / January 2006
Implementing the compareTo method
Paul Morrison - 09 Jan 2006 19:10 GMT 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
James Westby - 09 Jan 2006 20:07 GMT > Hi, > [quoted text clipped - 28 lines] > > 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
Paul Morrison - 09 Jan 2006 20:16 GMT >> public Edge compareTo(Edge e) { >> //to do [quoted text clipped - 7 lines] >> else >> return 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
James Westby - 09 Jan 2006 20:22 GMT >>> public Edge compareTo(Edge e) { >>> //to do [quoted text clipped - 15 lines] > > 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
Googmeister - 09 Jan 2006 20:57 GMT > 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).
James Westby - 09 Jan 2006 21:06 GMT >>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 [quoted text clipped - 7 lines] > 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.
Paul Morrison - 09 Jan 2006 20:25 GMT 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
>>> public Edge compareTo(Edge e) { >>> //to do [quoted text clipped - 15 lines] > > Paul James Westby - 09 Jan 2006 20:44 GMT > 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 [quoted text clipped - 15 lines] > > Paul Can i ask why you are using an ArrayList to store those four numbers? Is it always four numbers?
James
Paul Morrison - 09 Jan 2006 20:53 GMT > 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!
James Westby - 09 Jan 2006 21:02 GMT >>Can i ask why you are using an ArrayList to store those four numbers? Is >>it always four numbers? [quoted text clipped - 6 lines] > > 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)); }
}
}
Oliver Wong - 09 Jan 2006 21:04 GMT >> Can i ask why you are using an ArrayList to store those four numbers? Is >> it always four numbers? [quoted text clipped - 3 lines] > 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
Paul Morrison - 09 Jan 2006 21:34 GMT > You might want to define a class to encapsulate these for values. For > example: [quoted text clipped - 8 lines] > 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
Oliver Wong - 09 Jan 2006 22:01 GMT >> You might want to define a class to encapsulate these for values. For >> example: [quoted text clipped - 17 lines] > 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
Roedy Green - 09 Jan 2006 22:27 GMT >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.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Raymond DeCampo - 10 Jan 2006 16:05 GMT >>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. ...and you can use Arrays.asList() for interoperability with collections.
HTH, Ray
 Signature This signature intentionally left blank.
zero - 09 Jan 2006 20:35 GMT > 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.
 Signature Beware the False Authority Syndrome
Googmeister - 09 Jan 2006 21:00 GMT > > I have just looked, and it seems that the return type of compareTo has > > to be int. What exactly do I return? [quoted text clipped - 15 lines] > 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.
Roedy Green - 09 Jan 2006 22:10 GMT >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: see http://mindprod.com/jgloss/comparable.html
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Paul Morrison - 10 Jan 2006 19:18 GMT > 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
James Westby - 10 Jan 2006 19:28 GMT >>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 [quoted text clipped - 26 lines] > > 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
Paul Morrison - 10 Jan 2006 19:34 GMT > 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. Thank you James (and all others who helped), your help is much appreciated!
Paul
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|