2015-09-09 6 views
5

Consente Supponiamo che io ho il seguente elenco di mappeCome posso fare un ordinamento secondario in un elenco di mappe

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

prima voglio ordinare questa mappa dal conte e poi per nome:

Desiderate Resa:

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

ho provato quanto segue per eseguire la prima selezione, ma in grado di ordinare utilizzando nome dopo l'ordinamento per conteggio

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

Questo è stato compilato? Il tipo Raw 'Comparator' ha bisogno dei parametri' Object', non 'Integer'. – Codebender

+0

Non l'ho compilato. Ho appena dato un'idea di cosa sto cercando di fare –

+0

Qual è la rappresentazione del valore nella tua mappa. Presumo che Key sia integer. Ma come stai memorizzando i valori. Perché ci sono due cose in valore per la chiave data. – YoungHobbit

risposta

2

con Java 1.8, vorrei utilizzare i nuovi metodi di confronto (anche se la mancanza di inferenza di tipo rende necessario dichiarare tutti i tipi, riducendo la lisibility):

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"))); 

con Java 1.7, avrei probabilmente usare un chainedComparator (vedi di Apache ComparatorUtils o Guava di Ordering) e una MapValueComparator personalizzato (probabilmente ci sono uno in librerie comuni, ma non l'ho trovato). Poi l'ordinamento voluto ottenere abbastanza leggibile:

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") 
    ); 

E poi utilizzarlo (Java 7 o 8):

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

Rq: si dovrebbe, come affermato in altre risposte, verificare la presenza di valori nulli e le chiavi assenti in MapValueComparator.

4

Supponendo list s' è di tipo List<Map<String,Object>> (non è chiaro qual è il tipo del valore del Map, quindi ho usato Object), il vostro Comparator dovrebbe essere in grado di confrontare due istanze 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

Se ho capito correttamente, si dispone di un List<Map<String, Object>>. Avrai bisogno di scrivere un numero personalizzato Comparator per ordinarlo. Lì, si può confrontare ogni voce separatamente (gestione degli errori rimosso per 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); 
    }  
} 
Problemi correlati