Clasificación de HashMap por valores

Necesito ordenar mi HashMap según los valores almacenados en él. HashMap contiene el nombre de los contactos almacenados en el teléfono.

También necesito que las claves se clasifiquen automáticamente tan pronto como clasifique los valores, o puede decir que las claves y los valores están unidos, por lo que cualquier cambio en los valores debería reflejarse en las claves.

 HashMap map = new HashMap(); map.put(1,"froyo"); map.put(2,"abby"); map.put(3,"denver"); map.put(4,"frost"); map.put(5,"daisy"); 

Salida requerida:

 2,abby; 5,daisy; 3,denver; 4,frost; 1,froyo; 

Asumiendo Java, puedes ordenar hashmap así:

 public LinkedHashMap sortHashMapByValues( HashMap passedMap) { List mapKeys = new ArrayList<>(passedMap.keySet()); List mapValues = new ArrayList<>(passedMap.values()); Collections.sort(mapValues); Collections.sort(mapKeys); LinkedHashMap sortedMap = new LinkedHashMap<>(); Iterator valueIt = mapValues.iterator(); while (valueIt.hasNext()) { String val = valueIt.next(); Iterator keyIt = mapKeys.iterator(); while (keyIt.hasNext()) { Integer key = keyIt.next(); String comp1 = passedMap.get(key); String comp2 = val; if (comp1.equals(comp2)) { keyIt.remove(); sortedMap.put(key, val); break; } } } return sortedMap; } 

Solo un ejemplo de inicio. De esta forma es más útil, ya que ordena el HashMap y también conserva los valores duplicados.

Prueba el siguiente código, funciona bien para mí. Puedes elegir tanto Ascendente como Descendente

 import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; public class SortMapByValue { public static boolean ASC = true; public static boolean DESC = false; public static void main(String[] args) { // Creating dummy unsorted map Map unsortMap = new HashMap(); unsortMap.put("B", 55); unsortMap.put("A", 80); unsortMap.put("D", 20); unsortMap.put("C", 70); System.out.println("Before sorting......"); printMap(unsortMap); System.out.println("After sorting ascending order......"); Map sortedMapAsc = sortByComparator(unsortMap, ASC); printMap(sortedMapAsc); System.out.println("After sorting descindeng order......"); Map sortedMapDesc = sortByComparator(unsortMap, DESC); printMap(sortedMapDesc); } private static Map sortByComparator(Map unsortMap, final boolean order) { List> list = new LinkedList>(unsortMap.entrySet()); // Sorting the list based on values Collections.sort(list, new Comparator>() { public int compare(Entry o1, Entry o2) { if (order) { return o1.getValue().compareTo(o2.getValue()); } else { return o2.getValue().compareTo(o1.getValue()); } } }); // Maintaining insertion order with the help of LinkedList Map sortedMap = new LinkedHashMap(); for (Entry entry : list) { sortedMap.put(entry.getKey(), entry.getValue()); } return sortedMap; } public static void printMap(Map map) { for (Entry entry : map.entrySet()) { System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue()); } } } 

Editar: Versión 2

Se utilizó la nueva función de Java como secuencia para cada uno, etc.

El mapa se ordenará por claves si los valores son los mismos

  import java.util.*; import java.util.Map.Entry; import java.util.stream.Collectors; public class SortMapByValue { private static boolean ASC = true; private static boolean DESC = false; public static void main(String[] args) { // Creating dummy unsorted map Map unsortMap = new HashMap<>(); unsortMap.put("B", 55); unsortMap.put("A", 20); unsortMap.put("D", 20); unsortMap.put("C", 70); System.out.println("Before sorting......"); printMap(unsortMap); System.out.println("After sorting ascending order......"); Map sortedMapAsc = sortByValue(unsortMap, ASC); printMap(sortedMapAsc); System.out.println("After sorting descending order......"); Map sortedMapDesc = sortByValue(unsortMap, DESC); printMap(sortedMapDesc); } private static Map sortByValue(Map unsortMap, final boolean order) { List> list = new LinkedList<>(unsortMap.entrySet()); // Sorting the list based on values list.sort((o1, o2) -> order ? o1.getValue().compareTo(o2.getValue()) == 0 ? o1.getKey().compareTo(o2.getKey()) : o1.getValue().compareTo(o2.getValue()) : o2.getValue().compareTo(o1.getValue()) == 0 ? o2.getKey().compareTo(o1.getKey()) : o2.getValue().compareTo(o1.getValue())); return list.stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new)); } private static void printMap(Map map) { map.forEach((key, value) -> System.out.println("Key : " + key + " Value : " + value)); } } 

En Java 8:

 Map sortedMap = unsortedMap.entrySet().stream() .sorted(Entry.comparingByValue()) .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); 

No lo haces, básicamente. Un HashMap está fundamentalmente desordenado. No se debe confiar en los patrones que pueda ver en el orden.

Hay mapas ordenados como TreeMap , pero tradicionalmente clasifican por clave en lugar de valor. Es relativamente inusual ordenar por valor, especialmente porque varias claves pueden tener el mismo valor.

¿Puedes dar más contexto para lo que estás tratando de hacer? Si realmente solo está almacenando números (como cadenas) para las claves, ¿quizás un SortedSet como TreeSet funcionaría para usted?

Alternativamente, ¿podría almacenar dos colecciones separadas encapsuladas en una sola clase para actualizar ambas al mismo tiempo?

 package com.naveen.hashmap; import java.util.*; import java.util.Map.Entry; public class SortBasedonValues { /** * @param args */ public static void main(String[] args) { HashMap hm = new HashMap(); hm.put("Naveen", 2); hm.put("Santosh", 3); hm.put("Ravi", 4); hm.put("Pramod", 1); Set> set = hm.entrySet(); List> list = new ArrayList>( set); Collections.sort(list, new Comparator>() { public int compare(Map.Entry o1, Map.Entry o2) { return o2.getValue().compareTo(o1.getValue()); } }); for (Entry entry : list) { System.out.println(entry.getValue()); } } } 
 map.entrySet().stream() .sorted((k1, k2) -> -k1.getValue().compareTo(k2.getValue())) .forEach(k -> System.out.println(k.getKey() + ": " + k.getValue())); 

Como una especie de solución simple, puede usar Temp TreeMap si necesita solo un resultado final:

 TreeMap sortedMap = new TreeMap(); for (Map.Entry entry : map.entrySet()) { sortedMap.put((String) entry.getValue(), (Integer)entry.getKey()); } 

Esto te dará cadenas clasificadas como claves de sortedMap.

Extiendo un TreeMap y anulo los métodos entrySet () y values ​​(). La clave y el valor deben ser comparables.

Sigue el código:

 public class ValueSortedMap extends TreeMap { @Override public Set> entrySet() { Set> originalEntries = super.entrySet(); Set> sortedEntry = new TreeSet>(new Comparator>() { @Override public int compare(Entry entryA, Entry entryB) { int compareTo = entryA.getValue().compareTo(entryB.getValue()); if(compareTo == 0) { compareTo = entryA.getKey().compareTo(entryB.getKey()); } return compareTo; } }); sortedEntry.addAll(originalEntries); return sortedEntry; } @Override public Collection values() { Set sortedValues = new TreeSet<>(new Comparator(){ @Override public int compare(V vA, V vB) { return vA.compareTo(vB); } }); sortedValues.addAll(super.values()); return sortedValues; } } 

Pruebas unitarias:

 public class ValueSortedMapTest { @Test public void basicTest() { Map sortedMap = new ValueSortedMap<>(); sortedMap.put("A",3); sortedMap.put("B",1); sortedMap.put("C",2); Assert.assertEquals("{B=1, C=2, A=3}", sortedMap.toString()); } @Test public void repeatedValues() { Map sortedMap = new ValueSortedMap<>(); sortedMap.put("D",67.3); sortedMap.put("A",99.5); sortedMap.put("B",67.4); sortedMap.put("C",67.4); Assert.assertEquals("{D=67.3, B=67.4, C=67.4, A=99.5}", sortedMap.toString()); } } 

Encontré una solución pero no estoy seguro del rendimiento si el mapa tiene un tamaño grande, útil para el caso normal.

  /** * sort HashMap by value * CustomData needs to provide compareTo() for comparing CustomData * @param map */ public void sortHashMapByValue(final HashMap map) { ArrayList keys = new ArrayList(); keys.addAll(map.keySet()); Collections.sort(keys, new Comparator() { @Override public int compare(String lhs, String rhs) { CustomData val1 = map.get(lhs); CustomData val2 = map.get(rhs); if (val1 == null) { return (val2 != null) ? 1 : 0; } else if (val1 != null) && (val2 != null)) { return = val1.compareTo(val2); } else { return 0; } } }); for (String key : keys) { CustomData c = map.get(key); if (c != null) { Log.e("key:"+key+", CustomData:"+c.toString()); } } } 
 package SortedSet; import java.util.*; public class HashMapValueSort { public static void main(String[] args){ final Map map = new HashMap(); map.put(4,"Mango"); map.put(3,"Apple"); map.put(5,"Orange"); map.put(8,"Fruits"); map.put(23,"Vegetables"); map.put(1,"Zebra"); map.put(5,"Yellow"); System.out.println(map); final HashMapValueSort sort = new HashMapValueSort(); final Set> entry = map.entrySet(); final Comparator> comparator = new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry o2) { String value1 = o1.getValue(); String value2 = o2.getValue(); return value1.compareTo(value2); } }; final SortedSet> sortedSet = new TreeSet(comparator); sortedSet.addAll(entry); final Map sortedMap = new LinkedHashMap(); for(Map.Entry entry1 : sortedSet ){ sortedMap.put(entry1.getKey(),entry1.getValue()); } System.out.println(sortedMap); } } 
 public static TreeMap sortMap(HashMap passedMap, String byParam) { if(byParam.trim().toLowerCase().equalsIgnoreCase("byValue")) { // Altering the (key, value) -> (value, key) HashMap newMap = new HashMap(); for (Map.Entry entry : passedMap.entrySet()) { newMap.put(entry.getValue(), entry.getKey()); } return new TreeMap(newMap); } return new TreeMap(passedMap); } 
 import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; public class CollectionsSort { /** * @param args */`enter code here` public static void main(String[] args) { // TODO Auto-generated method stub CollectionsSort colleciotns = new CollectionsSort(); List list = new ArrayList(); HashMap h = new HashMap(); h.put("nayanana", 10); h.put("lohith", 5); for (Entry value : h.entrySet()) { combine a = colleciotns.new combine(value.getValue(), value.getKey()); list.add(a); } Collections.sort(list); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } public class combine implements Comparable { public int value; public String key; public combine(int value, String key) { this.value = value; this.key = key; } @Override public int compareTo(combine arg0) { // TODO Auto-generated method stub return this.value > arg0.value ? 1 : this.value < arg0.value ? -1 : 0; } public String toString() { return this.value + " " + this.key; } } }