2015-09-09 1 views
5

Lets Supposons que j'ai la liste suivante des cartesComment puis-je faire un tri secondaire sur la liste des cartes

[{id:1,count:2,name:xyz}, 
{id:2,count:3,name:def}, 
{id:3,count:2,name:abc}, 
{id:4,count:5,name:ghj} 
] 

Je veux d'abord trier cette carte en nombre et puis par nom:

souhaitee sortie:

[{id:3,count:2,name:abc}, 
{id:1,count:2,name:xyz}, 
{id:2,count:3,name:def}, 
{id:4,count:5,name:ghj} 
] 

j'ai essayé ce qui suit pour effectuer le premier tri, mais incapable de trier en utilisant le nom après le tri par comptage

Collections.sort(list, new Comparator() { 
     public int compare(Object o1, Object o2) { 
      return ((Comparable) ((Map.Entry) (o1)).getValue()) 
      .compareTo(((Map.Entry) (o2)).getValue()); 
     } 
+1

Est-ce que cela a même été compilé? Le type brut 'Comparator' nécessite les paramètres' Object', pas 'Integer'. – Codebender

+0

Je ne l'ai pas compilé. Je viens de donner une idée de ce que j'essaie de faire –

+0

Qu'est-ce que la représentation de la valeur dans votre carte. Je suppose que Key est Integer. Mais comment stockez-vous les valeurs? Parce qu'il y a deux choses en valeur pour la clé donnée. – YoungHobbit

Répondre

2

Avec Java 1.8, je voudrais utiliser les nouvelles méthodes de comparaison (même si l'absence d'inférence de type, il est nécessaire de déclarer tous les types, ce qui réduit la lisibilité):

final Comparator<Map<String, Comparable<Object>>> nameThenCountComparator = Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
      m -> m.get("name")).thenComparing(Comparator.<Map<String, Comparable<Object>>, Comparable<Object>> comparing(
      m -> m.get("count"))); 

Avec Java 1.7, je serais probablement utiliser un chainedComparator (voir Apache ComparatorUtils ou goyave de Ordering) et un MapValueComparator personnalisé (il y a probablement une dans les bibliothèques communes, mais n'a pas trouvé). Ensuite, l'ordre voulu obtenir assez lisible:

class MapValueComparator implements Comparator<Map<String, Object>> { 
     private final String key; 

     public MapValueComparator(final String key) { 
      this.key = key; 
     } 

     @Override 
     public int compare(final Map<String, Object> o1, final Map<String, Object> o2) { 
      return ((Comparable<Object>)o1.get(key)).compareTo(o2.get(key)); 
     } 
    } 

    Comparator<Object> nameThenCountComparator = ComparatorUtils.chainedComparator(
      new MapValueComparator("name"), 
      new MapValueComparator("count") 
    ); 

Et puis utilisez (Java 7 ou 8):

final List<Map<String, Comparable<Object>>> list = null; 
Collections.sort(list, nameThenCountComparator); 

Rq: vous devriez, comme indiqué dans d'autres réponses, vérifiez les valeurs NULL et les clés absents dans le MapValueComparator.

4

En supposant le type de list est List<Map<String,Object>> (il est pas clair quel est le type de la valeur de la Map, donc j'utilisé Object), votre Comparator devrait être en mesure de comparer les deux cas Map<String,Object>.

Collections.sort(list, new Comparator<Map<String,Object>>() { 
     public int compare(Map<String,Object> o1, Map<String,Object> o2) { 
      // first compare o1.get("count") to o2.get("count") 
      // if they are equal, compare o1.get("name") to o2.get("name") 
      // don't forget to handle nulls (for example if either o1 or o2 is null 
      // or if any of the keys are not present in one or both of the maps) 
     } 
2

Si je comprends bien, vous avez un List<Map<String, Object>>. Vous aurez besoin d'écrire un Comparator personnalisé pour le trier. Là, vous pouvez comparer chaque entrée séparément (traitement des erreurs enlevé pour bravity):

public class ListMapComparator implements Comparator<List<Map<String, Object>>> { 

    @Override 
    public in compare (List<Map<String, Object>> l1, List<Map<String, Object>> l2) { 
     Integer count1 = (Integer)l1.get("count"); 
     Integer count2 = (Integer)l2.get("count"); 
     int comp = count1.compare(count2); 
     if (comp != 0) { 
      return comp; 
     } 

     String name1 = (String)l1.get("name"); 
     String name2 = (String)l2.get("name"); 
     return name1.compare(name2); 
    }  
}