Re: Sorting based on multiple parameters
Manish Hatwalne wrote:
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?
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);
}
}