2016-11-02 1 views
1

j'ai cet objet ClientSearchJava tri avec plusieurs conditions de colonne

public class ClientSearch{ 
private Long clientNumber; 
private String queueNumber; 
private String clientName; 
private String customerName; 
..... 
} 

je dois régler ce problème par cette règle:

Afficher le ClientNumber descendant d'abord, puis par customerName descendant et après tous les enregistrements ClientNumber sont affiché, trier par queueNumber dans l'ordre décroissant et customerName dans l'ordre décroissant.

Cela devrait être le résultat --- ClientNumber desc puis, CustomerName desc, puis, QueueNumber desc puis, 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 

Fondamentalement, chaque objet a ClientSearch soit un ClientNumber ou un queueNumber (s'il n'y a pas numéro de client puis le numéro de queu est considéré comme un numéro de client c'est pourquoi il est affiché sous cette colonne),

ce que je pensais faire est, après avoir reçu une liste de ma requête (que je n'ai aucun contrôle, je viens de recevoir le Liste <>), je vais parcourir la liste avec la condition.

if clientNumber is present then add to a List<ClientSearch> withClientNumbers 

else if queueNumber is present then add to a List<ClientSearch> withQueueNumbers 

Après avoir fait cela, je vais trier les withClientNumbers avec un comparateur qui compare la ClientNumber du ClientSearch alors si elles sont égales à zéro mal faire autre comparer avec customerName de ClientSearch. J'ai juste besoin de les multiplier par -1 pour m'assurer que c'est DESC. Je ferai la même chose avec queueNumbers mais avec un comparateur différent.

puis Ill créer une nouvelle liste newList et fera ce

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. 

Pouvez-vous suggérer une autre façon élégante de le faire? Je sens que ma méthode n'est pas la plus optimisée. Prenez note que j'utilise Java 1.6

+0

dans votre table vous a montré « clientName », mais dans votre description textuelle, vous avez utilisé « customerName » dans les deux cas. Pouvez-vous clarifier cela? Et, quel est le problème faisant un comparateur comparant ClientNumber (null last) puis numéro de file d'attente, puis nom du client? –

+0

Note pour quiconque lisant ceci qui peut utiliser Java 8: Il y a une manière très élégante de chaîner les conditions de comparaison: 'humans.sort (Comparator.comparing (Human :: getName) .thenComparing (Human :: getAge));' Voir http : //www.baeldung.com/java-8-sort-lambda pour l'explication complète – Thirler

Répondre

2

En ce qui concerne le tri, il est généralement à peu près la façon dont vous allez mettre en œuvre le Comparator. Dans ce cas, vous avez simplement besoin d'un Comparator qui compare deux objets ClientSearch avec la manière que vous avez décrite.

Ce sera beaucoup plus propre si vous pouvez simplifier la nécessité de trier par

  1. Numéro de client (nulls dernières)
  2. ID de file d'attente, puis
  3. Nom du client

Le comparateur sera aussi simple que cela, avec Java 8:

import static java.util.Comparator.*; 
.... 
Comparator<Customer> comparator = 
    comparing(Customer::getCustNumber, nullsLast(naturalOrder())) 
    .thenComparing(Customer::getQueueId) 
    .thenComparing(Customer::getCustName); 

C'est un peu différent de ce que vous avez demandé à l'origine. Qu'est-ce que vous avez demandé est

  1. Si les deux ont le numéro de client, comparer par
    1. Numéro de client
    2. Nom du client
  2. Si les deux n'a pas numéro de client, comparer par
    1. ID de la file d'attente
    2. Nom du client
  3. Si l'un a le numéro de client alors que l'autre ne l'est pas, celui avec le numéro de client nul est traité comme supérieur.

Si vous avez vraiment besoin de ce que vous cherchez, ce n'est pas difficile à faire. Par exemple, vous pouvez avoir deux Comparator s chacun pour le cas séparé, et de combiner ensuite comme un Comparator, ressemble à quelque chose comme (avec l'aide de Java 8, ne devrait pas être difficile d'écrire un pour la version Java précédente si vous avez l'idée):

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; 
     } 
    } 
} 

(je crois que je ne ai pas besoin de vous dire comment faire le tri avec un Comparator droit?)


Mise à jour: Comme vous l'avez mentionné que vous utilisez Java 6, voici l'idée de base sur ce à quoi ressemblera ce comparateur (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; 
     } 
    } 

(il regardera mieux avec une réorganisation, ou avec l'aide d'outils comme goyave ou Apache Common Langs)

0

Le vôtre est correct, je viens de le tester comme ci-dessous. L'optimisation des notes est faite dans le tri et non dans la comparaison des fonctions. Puisque vous utiliserez la méthode de tri de Java own, vous n'avez pas à vous préoccuper de l'optimisation. Fondamentalement, vous venez de rompre les liens d'égalité de clientNumber avec customerNames. Ici, je prends des numéros de client comme numéro de client uniquement pour la simplicité. Puisque vous faites déjà des listes différentes, la même solution peut être appliquée aux deux listes et ensuite fusionner les listes. Exemple de code ci-dessous:

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(); 
     } 
    } 
}