por - sort map by key java 8
¿Cómo ordenar los valores del mapa por clave en Java? (13)
Tengo un mapa que tiene cadenas tanto para claves como para valores.
Los datos son como los siguientes:
"pregunta 1", "1"
"pregunta 9", "1"
"pregunta 2", "4"
"pregunta 5", "2"
Quiero ordenar el mapa en función de sus claves. Entonces, al final, tendré la question1, question2, question3
... y así sucesivamente.
Finalmente, estoy tratando de obtener dos cadenas de este mapa.
- Primera Cadena: Preguntas (en orden 1 ..10)
- Segunda cadena: Respuestas (en el mismo orden que la pregunta)
Ahora mismo tengo lo siguiente:
Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
questionAnswers += pairs.getKey() + ",";
}
Esto me pone las preguntas en una cadena pero no están en orden.
En java 8
Para ordenar un Map<K, V>
por clave, coloque las claves en una List<K>
:
List<K> result = map.keySet().stream().sorted().collect(Collectors.toList());
Para ordenar un Map<K, V>
por clave, List<Map.Entry<K, V>>
entradas en una List<Map.Entry<K, V>>
:
List<Map.Entry<K, V>> result =
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toList());
Por último, pero no menos importante: para ordenar las cadenas de una manera sensible al entorno local, use una Collator (comparador):
Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.PRIMARY); // case insensitive collator
List<Map.Entry<String, String>> result =
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey(collator))
.collect(Collectors.toList());
Respuesta corta
Utilice un TreeMap
. Esto es precisamente para lo que es.
Si se le pasa este mapa y no puede determinar el tipo, puede hacer lo siguiente:
SortedSet<String> keys = new TreeSet<>(map.keySet());
for (String key : keys) {
String value = map.get(key);
// do something
}
Esto recorrerá el mapa en orden natural de las teclas.
Respuesta más larga
Técnicamente, puedes usar cualquier cosa que implemente SortedMap
, pero excepto en casos raros, esto equivale a TreeMap
, del mismo modo que usar una implementación de Map
normalmente equivale a HashMap
.
Para los casos en que sus claves son un tipo complejo que no implementa Comparable o no desea utilizar el orden natural, TreeMap
y TreeSet
tienen constructores adicionales que le permiten pasar un Comparator
:
// placed inline for the demonstration, but doesn''t have to be a lambda expression
Comparator<Foo> comparator = (Foo o1, Foo o2) -> {
...
}
SortedSet<Foo> keys = new TreeSet<>(comparator);
keys.addAll(map.keySet());
Cuando use un TreeMap
o TreeSet
que tendrá características de rendimiento diferentes a las de HashMap
o HashSet
. En términos generales, las operaciones que encuentran o insertan un elemento irán de O (1) a O (Log (N)) .
En un HashMap
, pasar de 1000 elementos a 10,000 realmente no afecta su tiempo para buscar un elemento, pero para un TreeMap
el tiempo de búsqueda será aproximadamente 3 veces más lento (suponiendo el Registro 2 ). Pasar de 1000 a 100,000 será aproximadamente 6 veces más lento para cada búsqueda de elementos.
Asumir que TreeMap no es bueno para usted (y suponiendo que no puede usar genéricos):
List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.
En Java 8 también puedes usar .stream (). Sorted ():
myMap.keySet().stream().sorted().forEach(key -> {
String value = myMap.get(key);
System.out.println("key: " + key);
System.out.println("value: " + value);
}
);
Este código puede ordenar un mapa clave-valor en ambos órdenes, es decir, ascendente y descendente.
<K, V extends Comparable<V>> Map<K, V> sortByValues
(final Map<K, V> map, int ascending)
{
Comparator<K> valueComparator = new Comparator<K>() {
private int ascending;
public int compare(K k1, K k2) {
int compare = map.get(k2).compareTo(map.get(k1));
if (compare == 0) return 1;
else return ascending*compare;
}
public Comparator<K> setParam(int ascending)
{
this.ascending = ascending;
return this;
}
}.setParam(ascending);
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
sortedByValues.putAll(map);
return sortedByValues;
}
Como ejemplo:
Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1); // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1); // Descending order
Si ya tiene un mapa y desea clasificarlo por teclas, simplemente use:
Map<String, String> treeMap = new TreeMap<String, String>(yourMap);
Un ejemplo completo de trabajo:
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;
class SortOnKey {
public static void main(String[] args) {
HashMap<String,String> hm = new HashMap<String,String>();
hm.put("3","three");
hm.put("1","one");
hm.put("4","four");
hm.put("2","two");
printMap(hm);
Map<String, String> treeMap = new TreeMap<String, String>(hm);
printMap(treeMap);
}//main
public static void printMap(Map<String,String> map) {
Set s = map.entrySet();
Iterator it = s.iterator();
while ( it.hasNext() ) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
System.out.println(key + " => " + value);
}//while
System.out.println("========================");
}//printMap
}//class
Siempre que no pueda usar TreeMap
, en Java 8 podemos usar el método toMap() en Collectors
que toma los siguientes parámetros:
- keymapper : función de mapeo para producir claves
- valuemapper : función de mapeo para producir valores
- mergeFunction : una función de combinación, utilizada para resolver colisiones entre valores asociados con la misma clave
- mapSupplier : una función que devuelve un mapa nuevo y vacío en el que se insertarán los resultados.
Ejemplo de Java 8
Map<String,String> sample = new HashMap<>(); // push some values to map
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
.sorted(Map.Entry.<String,String>comparingByKey().reversed())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
Map<String, String> newMapSortedByValue = sample.entrySet().stream()
.sorted(Map.Entry.<String,String>comparingByValue().reversed())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));
Podemos modificar el ejemplo para usar un comparador personalizado y para ordenar según las claves como:
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
.sorted((e1,e2) -> e1.getKey().compareTo(e2.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));
Solo usa TreeMap
new TreeMap<String, String>(unsortMap);
Tenga en cuenta que el TreeMap se clasifica de acuerdo con el orden natural de sus ''claves''
También podemos ordenar la clave utilizando el método Arrays.sort.
Map<String, String> map = new HashMap<String, String>();
Object[] objArr = new Object[map.size()];
for (int i = 0; i < map.size(); i++) {
objArr[i] = map.get(i);
}
Arrays.sort(objArr);
for (Object str : objArr) {
System.out.println(str);
}
Usando el TreeMap
puedes ordenar el mapa.
Map<String, String> map = new HashMap<>();
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
System.out.println(str);
}
Utilice un TreeMap !
Utilizando Java 8:
Map<String, Integer> sortedMap = unsortMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
List<String> list = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String str : map.keySet()) {
list.add(str);
}
Collections.sort(list);
for (String str : list) {
System.out.println(str);
}