Java Forum / General / November 2007
Sorting based on multiple parameters
Manish Hatwalne - 14 Nov 2007 07:33 GMT I am little brain-dead today. Having problems writing comparator that will do comparison (for sorting) for multiple parameters.
Here is what I need to do - I have object MyObj with several fields. now I need to sort a collection of such objects based on list of fields supplied. So say if I want to sort MyObj collection based on fields "date" & "price" - similar to SQL "...order by date, price" - how do I do this?
Or in other words, how do I write comparator for following method?
[code] List sort(Collection<MyObj> objects, final List sortFields, final List<Enum.ASC/DESC> ascDesc){
} [/code]
any pointers, help would be highly appreciated!
TIA, - Manish
Jeff Higgins - 14 Nov 2007 12:31 GMT >I am little brain-dead today. Having problems writing comparator that will >do comparison (for sorting) for multiple parameters. [quoted text clipped - 13 lines] > } > [/code] Comparator interface contains only two methods: int compare(T o1, T o2) boolean equals(Object obj).
List interface contains no sort method. Collection interface contains no sort method.
Collections class contains two sort methods: static <T extends Comparable<? super T>> void sort(List<T> list) static <T> void sort(List<T> list, Comparator<? super T> c).
So, you'll have to write your own method.
Jeff Higgins - 14 Nov 2007 12:49 GMT >>I am little brain-dead today. Having problems writing comparator that will >>do comparison (for sorting) for multiple parameters. [quoted text clipped - 26 lines] > > So, you'll have to write your own method. Or extend Comparator.
Manish Hatwalne - 14 Nov 2007 14:27 GMT I am not sure if you understood the question.
"Or in other words, how do I write comparator for following method?"
I am writing thi smethod, and wondering how do I go about writing compareTo method for multiple parameters.
- Manish
Lew - 14 Nov 2007 14:59 GMT > I am not sure if you understood the question. > > "Or in other words, how do I write comparator for following method?" > > I am writing thi smethod, and wondering how do I go about writing compareTo > method for multiple parameters. Impute an order to null or default values for the missing parameters. For example, leave missing parms null and sort null values first or last.
public AFooComparator implements Comparator<Foo> { public void compare( Foo foo, Foo other ) { if ( other.getA() == null || getA().compareTo( other.getA() ) > 0 ) { return 1; } if ( getA().compareTo( other.getA() ) < 0 ) { return -1; } return 0; }
public ABFooComparator implements Comparator<Foo> { public void compare( Foo foo, Foo other ) { if ( other.getA() == null || getA().compareTo( other.getA() ) > 0 ) { return 1; } if ( getA().compareTo( other.getA() ) < 0 ) { return -1; } if ( other.getB() == null || getB().compareTo( other.getB() ) > 0 ) { return 1; } if ( getB().compareTo( other.getB() ) < 0 ) { return -1; } return 0; } }
etc.
 Signature Lew
Daniel Pitts - 14 Nov 2007 18:14 GMT > I am not sure if you understood the question. > [quoted text clipped - 4 lines] > > - Manish public int compareTo(Thing o) { final int r1 = field1.compareTo(o.field1); if (r1 != 0) { return r1; } final int r2 = field2.compareTo(o.field2); if (r2 != 0) { return r2; } return field3.compareTo(o.field3); }
 Signature Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jeff Higgins - 15 Nov 2007 00:33 GMT > I am not sure if you understood the question. > > "Or in other words, how do I write comparator for following method?" > > I am writing thi smethod, and wondering how do I go about writing > compareTo method for multiple parameters. Comparator interface has no compareTo method. Comparable interface has a single method: int compareTo(T o).
Manish Hatwalne - 15 Nov 2007 06:53 GMT > Comparator interface has no compareTo method. > Comparable interface has a single method: > int compareTo(T o). Sorry for confusion...I meant compare method of Comparator. Anyway - I have sensible pointers now to proceed further.
- Manish
Patricia Shanahan - 14 Nov 2007 14:48 GMT > I am little brain-dead today. Having problems writing comparator that will > do comparison (for sorting) for multiple parameters. [quoted text clipped - 14 lines] > > any pointers, help would be highly appreciated! Create an ArrayList<MyObj> using the Collection objects as the constructor parameter. Apply Collections.sort to the List<MyObj> with a Comparator to do the sorting.
That reduces the problem to writing a Comparator<MyObj> that orders based on a list of fields. Do you have a plan yet for specifying the list of fields? Are they all Comparable?
Patricia
Roedy Green - 15 Nov 2007 23:17 GMT On Wed, 14 Nov 2007 13:03:52 +0530, "Manish Hatwalne" <manish@nospam.com> wrote, quoted or indirectly quoted someone who said :
>I am little brain-dead today. Having problems writing comparator that will >do comparison (for sorting) for multiple parameters. see http://mindprod.com/jgloss/sort.html and http://mindprod.com/jgloss/comparator.html
There is a code for a Comparator that sorts arrays of fields, given a list of which cols to sort.
The basic idea is to compare a high order field. If they differ you are done. If not you compare the next higher order field.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Manish Hatwalne - 16 Nov 2007 04:16 GMT > The basic idea is to compare a high order field. If they differ you > are done. If not you compare the next higher order field. Well, that's all I needed to know when I posted the question. Now I have got it working. Thanks for being precise & helpful in your reply!
rgds, - Manish
Roedy Green - 15 Nov 2007 23:19 GMT On Wed, 14 Nov 2007 13:03:52 +0530, "Manish Hatwalne" <manish@nospam.com> wrote, quoted or indirectly quoted someone who said :
>I am little brain-dead today. Having problems writing comparator that will >do comparison (for sorting) for multiple parameters. Sort uses Comparable. You get only two parameters. These are references to Objects. Inside your compare method you look at the various fields in the objects.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Dave Stallard - 20 Nov 2007 05:20 GMT > I am little brain-dead today. Having problems writing comparator that will > do comparison (for sorting) for multiple parameters. [quoted text clipped - 3 lines] > So say if I want to sort MyObj collection based on fields "date" & "price" - > similar to SQL "...order by date, price" - how do I do this? Sorting a list of objects by some attribute or function of the object, rather than the object itself, is a frequent agony in Java. In the past, I've created all sorts of abstract classes (IntFunction, DoubleFunction, etc) to substitute for the lambda expression/closure language construct you really need for this. But I recently thought of a Better Way. <Smack forehead> that I did not think of it years ago.
A loose exposition:
// Prepping. This can be done in three lines if the value is an // expression. List<Comparable> values = new ArrayList<Comparable>(); for (Whatever x : list) { // Compute the value you want to sort on and add to list .... values.add(value); }
// Now the sorting, which calls the magic function. DONE! That's four // lines and minimal pain Sorting.sortAscending(list,values); // there's a sortDescending too
// How does it work? Here's the code.
// There's a sortDescending too. I can never remember the order so // I make it explicit in the name. public static void sortAscending (List objects, List<Comparable> values) { // Set up the sort pairs List<SortPair> sortPairs = new ArrayList<SortPair>(); for (int i=0;i<list.size();i++) sortPairs.add(new SortPair(list.get(i),values.get(i));
// Sort them Collections.sort(sortPairs);
// Stick the objects back in the list. That's it. for (int i=0;i<list.size();i++) list.set(i,sortPairs.get(i).object); }
// The SortPair can be an inner class of Sorting if desired class SortPair implements Comparable { Object object; Comparable value;
// SortPair (Object object, Comparable value) { this.object = object; this.value = value; }
// The compareTo just delegates to the object public int comparable (SortPair other) { return value.compareTo(other.value); } }
Lew - 20 Nov 2007 13:49 GMT > Sorting a list of objects by some attribute or function of the object, > rather than the object itself, is a frequent agony in Java. In the > past, I've created all sorts of abstract classes (IntFunction, > DoubleFunction, etc) to substitute for the lambda expression/closure > language construct you really need for this. Or you could sort using a Comparator<T> implementation of your own devise.
Such (usually anonymous) class overrides provide enough of the functionality of closures to do what's needed.
 Signature Lew
Lasse Reichstein Nielsen - 20 Nov 2007 17:37 GMT >> Sorting a list of objects by some attribute or function of the >> object, rather than the object itself, is a frequent agony in Java. [quoted text clipped - 3 lines] > > Or you could sort using a Comparator<T> implementation of your own devise. The problem with that is that if the sort keys needs (significant) computation, the comparator will compute it for each comparison.
Precomputing all the sort keys avoids that, but requires you to keep a pairing of sort keys and original values.
On the other hand, if comparison can be done directly on the values to be sorted, a comparator is definitly the way to go.
I've tried to make caching comparators, but I don't think it's worth the effort. I like the idea of having a sort on one array and rearranging another in the same way. It's fairly low-level, though, and I'd probably go for an interface like public <S,T> List<T> valuesSortedByKey(Map<S,T> pairs, Comparable<S> cmp);
Hmm, and again I misuse a Map as a collection of pairs. I really need tuples in this language!
/L
 Signature Lasse Reichstein Nielsen - lrn@hotpop.com DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html> 'Faith without judgement merely degrades the spirit divine.'
Dave Stallard - 22 Nov 2007 04:50 GMT >> Sorting a list of objects by some attribute or function of the object, >> rather than the object itself, is a frequent agony in Java. In the [quoted text clipped - 6 lines] > Such (usually anonymous) class overrides provide enough of the > functionality of closures to do what's needed. Yes, of course. You could exhaust yourself in intellectual onanism doing it the approved Java Way, by defining a whole new CLASS for each new sorting problem you have. Or you could do it my way:
List values = new ArrayList(); for (Object x : yourList) values.add(...arbitrary desired computation on x...); Sorting.sortAscending(yourList,values);
That's just four lines, all of them doing something, rather than building the same repetitive declarative scaffolding (a new Comparator class) to substitute for a language construct (closures/lambdas) which Java lacks. Which is less effort to write?
Of course better would be:
yourList.sort(lambda(x: ..your abitrary computation on x...));
Or perhaps still better, something like:
sort(x : yourList){ ...arbitrary computation on x..};
I personally find it clearer to have the variable bound in some quantifier-like construct, rather than to use a lambda. But all these notions are foreign to Java, with its puritanism about its "core language", which serves only to push all the vice into its libraries and programming idioms, thereby making its programmers neurotic, repressed, and anxious. ;)
Dave
Lew - 22 Nov 2007 04:53 GMT > I personally find it clearer to have the variable bound in some > quantifier-like construct, rather than to use a lambda. But all these > notions are foreign to Java, with its puritanism about its "core > language", which serves only to push all the vice into its libraries and > programming idioms, thereby making its programmers neurotic, repressed, > and anxious. ;) Whew! That's quite a rant!
 Signature Lew
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 ...
|
|
|