2011-03-01 30 views
20

que tienen una variable lista creada de esta manera:ordenar una lista de Mapa <String, String>

List<Map<String, String>> list = new ArrayList<Map<String, String>>();

En mi aplicación para Android, esta lista se rellena.

sólo un ejemplo:

Map<String, String> map1 = new HashMap<String, String>(); 
map.put("name", "Josh"); 
... 

Map<String, String> map2 = new HashMap<String, String>(); 
map.put("name", "Anna"); 
... 

Map<String, String> map3 = new HashMap<String, String>(); 
map.put("name", "Bernie"); 
... 

list.add(map1); 
list.add(map2); 
list.add(map3); 

estoy usando list para mostrar los resultados en un ListView extendiendo BaseAdapter e implementación de los diversos métodos.

Mi problema: Necesito clasificar list en orden alfabético basado en el mapa de teclado nombre

Pregunta: ¿Cuál es una manera sencilla de solucionar list en orden alfabético basado en clave el nombre del mapa?

Parece que no puedo entender esto. He extraído cada nombre de cada Map en una matriz String, y lo he ordenado (Arrays.sort(strArray);). Pero eso no quiere preservar los demás datos de cada Map, así que no estoy muy seguro de cómo puedo conservar los otros valores asignados

+4

@DLK, y saber cómo escribir un comparador personalizado es justo lo que binnyb está descubriendo. –

+1

Tanto las respuestas de @Jon Skeet como de @JB Nizet han señalado correctamente que 'Map' es probablemente una mala opción para sus registros. Una clase personalizada con atributos/getters/setters sería mejor. ¿Por qué? 1) robustez/tipo de seguridad, 2) uso de memoria, 3) rendimiento, 4) código más simple. –

+0

gracias por la sugerencia, voy a buscar cambiar cómo lo tengo configurado. – binnyb

Respuesta

29

El siguiente código funciona perfectamente

public Comparator<Map<String, String>> mapComparator = new Comparator<Map<String, String>>() { 
    public int compare(Map<String, String> m1, Map<String, String> m2) { 
     return m1.get("name").compareTo(m2.get("name")); 
    } 
} 

Collections.sort(list, mapComparator); 

Pero sus mapas, probablemente debería ser instancias de una clase específica.

+0

gracias, esto lo hizo (con correcciones de sintaxis menores). Estaré buscando crear una clase específica para la lista, nunca pensé en hacer eso. – binnyb

+2

No sé qué almacena en los mapas, pero si solo son atributos estáticos, (nombre, primer nombre, edad, etc.), incluso debería reemplazar el mapa por una clase (ejemplo: clase Persona {nombre de cadena privada) ; Private String firstName, etc.) –

5

debe implementar un Comparator<Map<String, String>> que básicamente extrae el valor "nombre" de los dos mapas Es pasado, y los compara.

Luego use Collections.sort(list, comparator).

¿Estás seguro de que Map<String, String> es realmente el mejor elemento para tu lista? Quizás debería tener otra clase que contiene a Map<String, String> pero también tiene un método getName()?

6
@Test 
public void testSortedMaps() { 
    Map<String, String> map1 = new HashMap<String, String>(); 
    map1.put("name", "Josh"); 

    Map<String, String> map2 = new HashMap<String, String>(); 
    map2.put("name", "Anna"); 

    Map<String, String> map3 = new HashMap<String, String>(); 
    map3.put("name", "Bernie"); 

    List<Map<String, String>> mapList = new ArrayList<Map<String, String>>(); 
    mapList.add(map1); 
    mapList.add(map2); 
    mapList.add(map3); 

    Collections.sort(mapList, new Comparator<Map<String, String>>() { 
     public int compare(final Map<String, String> o1, final Map<String, String> o2) { 
      return o1.get("name").compareTo(o2.get("name")); 
     } 
    }); 

    Assert.assertEquals("Anna", mapList.get(0).get("name")); 
    Assert.assertEquals("Bernie", mapList.get(1).get("name")); 
    Assert.assertEquals("Josh", mapList.get(2).get("name")); 

} 
+1

Esto se ha publicado hace 20 minutos ... –

4

Necesita crear un comparador. No estoy seguro de por qué cada valor necesita su propio mapa, pero aquí es lo que el comparador se vería así:

class ListMapComparator implements Comparator { 
    public int compare(Object obj1, Object obj2) { 
     Map<String, String> test1 = (Map<String, String>) obj1; 
     Map<String, String> test2 = (Map<String, String>) obj2; 
     return test1.get("name").compareTo(test2.get("name")); 
    } 
} 

Se puede ver el trabajo con su ejemplo anterior con esto:

public class MapSort { 
    public List<Map<String, String>> testMap() { 
     List<Map<String, String>> list = new ArrayList<Map<String, String>>(); 
     Map<String, String> myMap1 = new HashMap<String, String>(); 
     myMap1.put("name", "Josh"); 
     Map<String, String> myMap2 = new HashMap<String, String>(); 
     myMap2.put("name", "Anna"); 

     Map<String, String> myMap3 = new HashMap<String, String>(); 
     myMap3.put("name", "Bernie"); 


     list.add(myMap1); 
     list.add(myMap2); 
     list.add(myMap3); 

     return list; 
    } 

    public static void main(String[] args) { 
     MapSort ms = new MapSort(); 
     List<Map<String, String>> testMap = ms.testMap(); 
     System.out.println("Before Sort: " + testMap); 
     Collections.sort(testMap, new ListMapComparator()); 
     System.out.println("After Sort: " + testMap); 
    } 
} 

Usted tendrá algunos tipos de advertencias seguras porque no me preocupé por esto. Espero que ayude.

0
try { 
     java.util.Collections.sort(data, 
       new Comparator<Map<String, String>>() { 
        SimpleDateFormat sdf = new SimpleDateFormat(
          "MM/dd/yyyy"); 

        public int compare(final Map<String, String> map1, 
          final Map<String, String> map2) { 
         Date date1 = null, date2 = null; 
         try { 
          date1 = sdf.parse(map1.get("Date")); 
          date2 = sdf.parse(map2.get("Date")); 
         } catch (ParseException e) { 
          e.printStackTrace(); 
         } 
         if (date1.compareTo(date2) > 0) { 
          return +1; 
         } else if (date1.compareTo(date2) == 0) { 
          return 0; 
         } else { 
          return -1; 
         } 
        } 
       }); 

    } catch (Exception e) { 

    } 

0

poco fuera de tema
esto es un poco util para SharedPreferences viendo
basados ​​en respuestas superiores
puede ser para alguien que esto sea útil

@SuppressWarnings("unused") 
public void printAll() { 
    Map<String, ?> prefAll = PreferenceManager 
     .getDefaultSharedPreferences(context).getAll(); 
    if (prefAll == null) { 
     return; 
    } 
    List<Map.Entry<String, ?>> list = new ArrayList<>(); 
    list.addAll(prefAll.entrySet()); 
    Collections.sort(list, new Comparator<Map.Entry<String, ?>>() { 
     public int compare(final Map.Entry<String, ?> entry1, final Map.Entry<String, ?> entry2) { 
      return entry1.getKey().compareTo(entry2.getKey()); 
     } 
    }); 
    Timber.i("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
    Timber.i("Printing all sharedPreferences"); 
    for(Map.Entry<String, ?> entry : list) { 
     Timber.i("%s: %s", entry.getKey(), entry.getValue()); 
    } 
    Timber.i("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
} 
1

si desea hacer uso de lamdas y hacer que sea un poco más fácil de leer

List<Map<String,String>> results; 

    Comparator<Map<String,String>> sortByName = Comparator.comparing(x -> x.get("Name")); 

    public void doSomething(){ 
    results.sort(sortByName) 
    }