This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I have 2 jsp screens, on the first screen I input the search-sort criteria and on the second screen I am displaying a list of sorted variables from an object. I am using struts.
Following is info of what is displayed on the 2nd screen.
On the first jsp screen (where we have the search criteria) there are 3 selects (ie drop downs) the user will select 3 out the 8 variables above. For example: the user may select sort by First Name, City, and office Code. Another user may select sort by City, transfer date, Account type. So the user has a choice to choose any 3 out of the 8 variables above. After clicking search, I am populating the objects that have the above variables in an arraylist and then I am trying to programmatically sort this arraylist of objects before displaying them on the second screen. Please help how could I modify the comparator example code below.
I have assumed the above code with a search criteria by FirstName then City then OfficeCode. But in real time the user can choose any of the three from the 8 variables dynamically, then how would I code for that.
Jeff, I would like to go with either option 2 or 3. But can you explain them more, in a code or something for more clarity. I am not good at these reflections or mappings thing.
Thanks a lot for your time again.
Okay, first, do you know how to write a simple Comparator to compare on a single, predetermined field? For instance, "Write a Comparator that can be used to sort a list of Person objects by lastName." Have you ever done that? If not, you MUST do that before you go any further. If you don't, you're wasting your time and the time of anybody trying to help you here.
Next, do you understand how to write a Comparator to order based on multiple predetermined fields? For instance, "Write a Comparator that can be used to sort a list of Person objects by lastName and then if lastName is equal by firstName." Have you ever done that? If not, then, again, you MUST do this first.
Okay, so, now that you understand that stuff...
If you're going to go with a single Comparator, then you have to be able to tell that Comparator which fields to compare, right? And you need a way to get from those field names to the actual values in the fields being compared, right?
So, which approach do you want to take? #2 reflection or #3 custom mapping? Pick one, study up on it, take your best shot, and post again if you get stuck. (After first making sure you can work with Comparators where the fields aren't being chosen on the fly, of course.)
Here I am using only 2 variables to sort. That is Sortby variable1, Sortby variable2. The question I have is if I increase the number of variables to sort then the combinations also increase in the "compare" method for DynamicComparator.java. Is there way you would suggest?
I'd suggest creating a CompoundComparator class. This class would implement the Comparator interface, and take a list of Comparators in its constructor. The compare() method would then try all the comparators in the order in which they were given and returned the first nonzero value returned by one of the comparators. If all comparators return zero, the CompoundComparator returns zero as well. You should be able to code the class in a few minutes. It can easily be made generic.
Create a comparator or comparators to compare by one field at a time. Do it whatever you like - reflection, static code, anything. All you need is to be able to create comparator for a given field dynamically.
Take a list of requested fields and create a corresponding list of comparators. Create a CompoundComparator from that list.
If you want to reverse the order of comparison for one field, use Collections.reverseOrder(). You can then invert the order of any comparator in the CompoundComparator class independently of the others.
Luke Zechariah wrote:Here is the below code for sorting using reflections.
Personally, I would only use reflection if I was planning to write some sort of "universal" Comparator (ie, one which doesn't even know the class it's trying to compare); but I have to admit to an extreme aversion to reflection code.
Secondly, I think that converting to Strings is not a good idea (it rarely is) - you're likely to get bogged down in the detail of how each field gets converted.
An alternative would be to impose the simple rule that every field to be compared must be Comparable. This is already the case for Strings; and will also be the case for any boxed number. If your AccountInfo class contains any other fields that aren't, you have two choices:
1. Make them Comparable.
2. Don't allow them to be chosen.
I think I'd probably create an enum which includes all the sortable fields in your Account object, viz:and then use that to create a dynamic Comparator, viz:The nice thing about that is that you can then just associate any given column with an AccountField value.
Of course, it's only one possibility; and there are lots of others ([Edit] and now I've looked at Martin's suggestion properly, it's probably even better).
I should also point out that I haven't tried (or compiled) the above; but I'm pretty sure the idea is sound.
Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Joined: Sep 27, 2005
Thank you Martin and Winston for the input. Winston thanks for the code, I will test my code per your suggestion and see how it works. I took up Martin's suggestion and it is working. Here is code of what I did, I used ComparatorChain and sorted it.
You can add any number of variables to your POJO, and sort them accordingly.
Thank you everyone for your time and consideration.