Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2007

Tip: Looking for answers? Try searching our database.

Sorting based on multiple parameters

Thread view: 
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 Magazines

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

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.