• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Help needing in using Comparator to sort BY multiple elements in ArrayList

 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a a list called commonList.getCommonListItems.

In this list I have multiple elements and I'm needing to sort by 2 elements within this list: first by binSortCode and then by itemDescr

I've been googling and trying to get some help but am having problems trying to understanding comparable vs comparator. I had used comparable to sort on a single element and it worked find but when trying to sort on multiple elements I'm not able to make it work.

I have created a comparator class where I am trying to sort first on binSortCode and then sort on itemDesc, please see the following:



The outcome that I'm getting is that the binSortCode is in desc order and the itemdesc is in asc order.

As stated above, I need the sort to reflect: binSortCode in ASC order and then the itemDesc in ASC order.

Any help or direction would be greatly appreciated.

Regards.
 
Robert Waals
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
An object implementing the Comparable interface defines how to compare itself against other objects. When implementing this interface you have to implement the compareTo method. For more information click here.

A Comparator class allows you to sort on the criteria you specify yourself (or by using the compareTo method when you want to use both approaches). To sort on multiple levels you can create a nested Comparator class.

A small example:



This can then be used in the following way:


Regards,
Robert Jan
 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Robert,

I guess I'm not clear by what you sent. Are you saying that I need to add this CompositeComparator class to work with what I already have?
 
Campbell Ritchie
Sheriff
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is a simpler alternative, which is to sort with two different Comparators one after the other. More details in the API where the important fact is that the sort is "stable."
 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell,

I tried doing what you've suggested but it did not keep the sort from the first comparator and just overwrote what sort was there with the second comparator.

I'll look at he API again. Perhaps I did something wrong.
 
Ankit Garg
Sheriff
Posts: 9519
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:There is a simpler alternative, which is to sort with two different Comparators one after the other.


Well Campbell I don't know if I am right, but I think this will not work. If I understand it correctly, the sorting is to be done in this manner

Suppose I have a student class with fields name and age. Now I have to sort it with Age and if age is same for two or more children, then I have to sort them according to their name. Example if I have this list

Ankit, 20
Mayur, 23
Ram, 20
Aakash, 23

Then the sorting should be

Ankit, 20
Ram, 20
Aakash, 23
Mayur, 23

This can be done by using the comparator that you have already implemented. I made this code to show the functionality

 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ankit,

I think your example looks exactly, or almost, like the code that I'm having issues with that I posted initially.

However, the sort is not being done first by the binSortCode and THEN by the itemdesc fields. That is where my dilemma is.

The sort results I got where:

the binSortCode was in DESC order and the itemDesc was in ASC order.

I need the binSortCode to sort first then followed by the itemDesc to sort second maintaining the first sort of the binSortCode.

Hope that makes sense. Can you please look at the initial post? Thanks.
 
Ankit Garg
Sheriff
Posts: 9519
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you do two things. Just post the code of the CommonListItem class and also try compareTo instead of compareToIgnoreCase...
 
Jelle Klap
Bartender
Posts: 1951
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ankit Garg wrote:
Campbell Ritchie wrote:There is a simpler alternative, which is to sort with two different Comparators one after the other.


Well Campbell I don't if I am right, but I think this will not work. If I understand it correctly, the sorting is to be done in this manner


It should work if the sorting alorithm is stable (meaning equal objects aren't reorderd), like Campbell said.
For instance, let's say you have an unsorted list of objects, each of which contains two fields. This could be represented by the following sequence:

D, 3
A, 2
D, 6
A, 8
B, 5
A, 3
C, 1

Now, let's say you want this list to be first sorted alphabetically (ignoring character case for the sake of simplicitly) by the first column and then nummerically by the by the second column.
Let's say you've written two distinct Comparator implementations that do just that. First you should use the Comparator that sorts the list nummerically - which is the least significant field in the overall sorting sequence.
You'll end up with the following sequence:

C, 1
A, 2
D, 3
A, 3
B, 5
D, 6
A, 8

Obviously you're not there yet, because you still have to meet the primary sorting requirement, so let's apply that Comparator to the intermediate result:

A, 2
A, 3
A, 8
B, 5
C, 1
D, 3
D, 6

Et voilá! If you apply the Comparators sequentially in a back-to-front order (i.e. first sorting by the field that the final sequence should be ordered by last) it all works out beautifully.
 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ankit,

Here is the CommonListItem class and I will try to just use compare method, thanks :

 
Ankit Garg
Sheriff
Posts: 9519
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle you are right. I have never every thought or heard about that solution. I was hesitating to write that Campbell was wrong as I know that he is among the most respected people out here. That's why I wrote

I don't know if I am right, but I think this will not work


I knew that I would be wrong at the end

I still have a lot to learn before I can dare to directly say that Campbell you are wrong
 
Ankit Garg
Sheriff
Posts: 9519
22
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Melinda I don't see anything wrong with that code. Why don't you try what Campbell and Jelle said i.e. implement two comparators...
 
Melinda Savoy
Ranch Hand
Posts: 387
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for all the help. I will try my initial code again.

Regards.
 
Campbell Ritchie
Sheriff
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why don't you tell me when you think I am wrong? Joanne Neal does all the time!

Actually, you are right. You have to implement one Comparator, then if that returns 0 try the other Comparator. Since the sorting is "stable", if both Comparators return 0, then the two elements are left in their initial locations.

Anyway some good came of it; my mistake made for a much more interesting discussion.
 
Campbell Ritchie
Sheriff
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By the way, that equals() method looks suspect to me. The equals() method takes Object as a parameter, so you can pass any reference type to it, but anything other than the correct type will generate a ClassCastException. You need to test for type (details in books like Effectvie Java by Joshua Bloch, or on that most useful website of Angelika Langer's), and you also need to override the Object#hashCode() method.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic