Sorting based on multiple parameters

M

Manish Hatwalne

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){

}

any pointers, help would be highly appreciated!

TIA,
- Manish
 
J

Jeff Higgins

Manish said:
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){

}

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.
 
J

Jeff Higgins

Jeff said:
Manish said:
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){

}

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.

Or extend Comparator.
 
M

Manish Hatwalne

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
 
P

Patricia Shanahan

Manish said:
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){

}

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
 
L

Lew

Manish said:
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.
 
D

Daniel Pitts

Manish said:
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
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);
}
 
J

Jeff Higgins

Manish said:
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).
 
M

Manish Hatwalne

Jeff Higgins said:
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
 
R

Roedy Green

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.
 
M

Manish Hatwalne

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
 
D

Dave Stallard

Manish said:
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);
}
}
 
L

Lew

Dave said:
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.
 
L

Lasse Reichstein Nielsen

Lew said:
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
 
D

Dave Stallard

Lew said:
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.

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
 
L

Lew

Dave said:
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!
 

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,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top