Reputation: 607
I have this object ClientSearch
public class ClientSearch{
private Long clientNumber;
private String queueNumber;
private String clientName;
private String customerName;
.....
}
I need to sort this by this rule:
Show the clientNumber descending first then by customerName descending and after all records with clientNumber are displayed, sort by queueNumber in descending order and customerName in descending order.
This should be the result --- ClientNumber desc then, CustomerName desc, then, QueueNumber desc then, CustomerName desc
ClientNumber ClientName CustomerName
987654 Client1 Xyz1
987654 Client2 Abc2
555555 Client3 zzzzz1
21212 XYZ1 aaaab
111111 Client10 cZ
111111 Client11 cY
Z1Z1Z1 ClientX zzzzz
Z1Z1Z1 ClientY yyyyy
X2X2X2 Clienxyz aaaaaa
HHHHHH ClientH bbbbbb
AAAAAA ClientA xxxxxx
Basically each ClientSearch object has either a clientNumber or a queueNumber (if there is no client number then the queuNumber is considered a client number thats why it is displayed under that column),
what I thought of doing is, after I receive a List from my query (which I have no control, I just received the List<>), i will iterate through the list with the condition.
if clientNumber is present then add to a List<ClientSearch> withClientNumbers
else if queueNumber is present then add to a List<ClientSearch> withQueueNumbers
After doing this, I'll sort the withClientNumbers with a Comparator that compares the ClientSearch's clientNumber then if they are equal to zero ill do another compare with ClientSearch's customerName. I just need to multiply these with -1 to make sure it is DESC.
I'll do the same with queueNumbers but with a different comparator.
then Ill create a new List newList and then will do this
newList.addAll(withClientNumbers); //make sure this is first in the list
newList.addAll(queueNumbers); // so to satisfy the condition that queueNumbers are shown after a sorted clientNumbers.
Can you suggest any other elegant way to do this? I feel that my method is not the most optimized one. Take note that I'm using Java 1.6
Upvotes: 1
Views: 1278
Reputation: 40036
When it comes to sorting, it is usually just about how you are going to implement the Comparator
. In such case, you simply need a Comparator
that compares two ClientSearch
objects with the way you described.
It will be much cleaner if you can simplify your requirement to sort by
The comparator will be as easy as this, with Java 8:
import static java.util.Comparator.*;
....
Comparator<Customer> comparator =
comparing(Customer::getCustNumber, nullsLast(naturalOrder()))
.thenComparing(Customer::getQueueId)
.thenComparing(Customer::getCustName);
It is a bit different from what you originally asked for. What you asked for is
If you really need what you are looking for, it is not difficult to do. For example, you can have two Comparator
s each for the separate case, and combine then as one Comparator
, looks something like (with aid of Java 8, should not be difficult to write one for prev Java version if you get the idea):
public class ClientSearchComparator implements Comparator<ClientSearch> {
private static Comparator<ClientSearch> custNumberComparator =
Comparator.comparing(ClientSearch::getCustNumber)
.thenComparing(ClientSearch::getCustName);
private static Comparator<ClientSearch> queueIdComparator =
Comparator.comparing(ClientSearch::getQueueId)
.thenComparing(ClientSearch::getCustName);
@Override
public int compare(ClientSearch c1, ClientSearch c2) {
if (c1.getCustNumber() != null && c2.getCustNumber() != null) {
return custIdComparator.compare(c1, c2);
} else if (c1.getCustNumber() == null && c2.getCustNumber() == null) {
return queueIdComparator.compare(c1, c2);
} else if (c1.getCustNumber() != null && c2.getCustNumber() == null) {
return -1;
} else { // (c1.getCustNumber() == null && c2.getCustNumber() != null)
return 1;
}
}
}
(I believe I do not need to tell you how to do sorting with an Comparator
right?)
Update: As you have mentioned that you are using Java 6, here is the basic idea on what that Comparator will look like (pseudo-code):
public class ClientSearchComparator implements Comparator<ClientSearch> {
@Override
public int compare(ClientSearch c1, ClientSearch c2) {
if (c1.custNum != null && c2.custNum != null) {
if (c1.custNum != c2.custNum) {
return c1.custNum.compareTo(c2.custNum);
}
return c1.custName.compareTo(c2.custName);
} else if (c1.custNum == null && c2.custNum == null) {
if (c1.queueId != c2.queueId) {
return c1.queueId .compareTo(c2.queueId);
}
return c1.custName.compareTo(c2.custName);
} else if (c1.custNum == null) { // c1 null && c2 not null
return 1;
} else { // c1 not null && c2 null
return -1;
}
}
(it will look better with some reorganization, or with aid of tools like Guava or Apache Common Langs)
Upvotes: 2
Reputation: 2691
Yours is correct way, I just tested it as below. Note optimization is done in sorting and not in comparing functions. Since you will be using Java own's sorting method you don't have to worry about optimization. Basically you are just breaking off ties of equality of clientNumber with customerNames. Here I am taking queuenumbers as clientnumbers only for simplicity. Since you are already making different lists same solution can be applied to both lists and then merge the lists. Sample code below :
public class ClientSearch{
private String clientNumber;
// private String queueNumber;
private String clientName;
private String customerName;
public ClientSearch(String clientNumber, String clientName, String customerName) {
this.clientNumber = clientNumber;
//this.queueNumber = queueNumber;
this.clientName = clientName;
this.customerName = customerName;
}
public String toString(){
return clientNumber+" "+clientName+" "+customerName;
}
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
String tmp = null;
List<ClientSearch> list = new ArrayList<>();
while((tmp=br.readLine())!=null){
String split [] = tmp.split(" ");
list.add(new ClientSearch(split[0],split[1],split[2]));
}
System.out.println("Sorting.....");
list.sort(new Comparator<ClientSearch>() {
@Override
public int compare(ClientSearch o1, ClientSearch o2) {
int diff = o1.clientNumber.compareTo(o2.clientNumber);
return diff ==0 ? o1.customerName.compareTo(o2.customerName) : diff;
}
});
for (ClientSearch c : list){
System.out.println(c);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Upvotes: 0