我有这个对象ClientSearch
public class ClientSearch{
private Long clientNumber;
private String queueNumber;
private String clientName;
private String customerName;
.....
}
我需要按照这条规则对此进行排序:
显示clientNumber先降序,然后按customerName降序显示,显示所有带有clientNumber的记录后,按降序排列queueNumber,按降序排序。
这应该是结果--- ClientNumber desc然后,CustomerName desc,然后,QueueNumber desc,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
基本上每个ClientSearch对象都有一个clientNumber或一个queueNumber(如果没有客户端编号,则将queuNumber视为一个客户端编号,说明它在该列下显示的原因),
我想做的是,在我从查询中收到一个List(我无法控制,我刚刚收到List<>)之后,我将使用条件遍历列表。
if clientNumber is present then add to a List<ClientSearch> withClientNumbers
else if queueNumber is present then add to a List<ClientSearch> withQueueNumbers
执行此操作后,我会使用比较ClientClumber的clientNumber的比较器对withClientNumbers进行排序,然后如果它们等于0,则与ClientSearch的customerName进行比较。我只需要将它们与-1相乘以确保它是DESC。
我将对queueNumbers执行相同操作,但使用不同的比较器。
然后我创建一个新的List newList,然后执行此操作
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.
你能建议任何其他优雅的方式吗?我觉得我的方法不是最优化的方法。请注意我使用的是Java 1.6
答案 0 :(得分:2)
在排序方面,通常只是关于如何实施Comparator
。在这种情况下,您只需要一个Comparator
,可以按照您描述的方式比较两个ClientSearch
个对象。
如果您可以简化排序要求
,那将会更加清晰比较器将如此简单,使用Java 8:
import static java.util.Comparator.*;
....
Comparator<Customer> comparator =
comparing(Customer::getCustNumber, nullsLast(naturalOrder()))
.thenComparing(Customer::getQueueId)
.thenComparing(Customer::getCustName);
与您最初要求的有点不同。你要的是
如果你真的需要你想要的东西,那就不难做到。例如,对于单独的case,你可以有两个Comparator
,然后将它们合并为一个Comparator
,看起来像(借助Java 8,对于prev Java来说应该不难写)版本如果你明白了):
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;
}
}
}
(我相信我不需要告诉你如何使用Comparator
进行排序?)
更新: 正如您所提到的那样,您使用的是Java 6,这里是关于Comparator的基本概念(伪代码):
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;
}
}
(通过一些重组,或者使用像Guava或Apache Common Langs这样的工具,它看起来会更好)
答案 1 :(得分:0)
你的方法是正确的,我只是测试如下。注意优化在排序中完成,而不是在比较函数中完成。由于您将使用Java自己的排序方法,因此您不必担心优化。 基本上你只是断开clientNumber与customerNames的平等关系。在这里,我只是为了简单而将queuenumbers作为客户端数。由于您已经在制作不同的列表,因此可以将相同的解决方案应用于两个列表,然后合并列表。示例代码如下:
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();
}
}
}