Sorting HashMap by values
本问题已经有最佳答案,请猛点这里访问。
我需要根据存储在其中的值对我的
另外,我需要在对值进行排序时自动对键进行排序,也可以说键和值是绑定在一起的,因此任何值的更改都应该反映在键中。
1 2 3 4 5 6 |
所需输出:
1 2 3 4 5 | 2,abby; 5,daisy; 3,denver; 4,frost; 1,froyo; |
试试下面的代码,它对我来说很好。您可以选择升序和降序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 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<String, Integer> unsortMap = new HashMap<String, Integer>(); 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<String, Integer> sortedMapAsc = sortByComparator(unsortMap, ASC); printMap(sortedMapAsc); System.out.println("After sorting descindeng order......"); Map<String, Integer> sortedMapDesc = sortByComparator(unsortMap, DESC); printMap(sortedMapDesc); } private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order) { List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet()); // Sorting the list based on values Collections.sort(list, new Comparator<Entry<String, Integer>>() { public int compare(Entry<String, Integer> o1, Entry<String, Integer> 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<String, Integer> sortedMap = new LinkedHashMap<String, Integer>(); for (Entry<String, Integer> entry : list) { sortedMap.put(entry.getKey(), entry.getValue()); } return sortedMap; } public static void printMap(Map<String, Integer> map) { for (Entry<String, Integer> entry : map.entrySet()) { System.out.println("Key :" + entry.getKey() +" Value :"+ entry.getValue()); } } } |
编辑:版本2
Used new java feature like stream for-each etc
Map will be sorted by keys if values are same
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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<String, Integer> 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<String, Integer> sortedMapAsc = sortByValue(unsortMap, ASC); printMap(sortedMapAsc); System.out.println("After sorting descending order......"); Map<String, Integer> sortedMapDesc = sortByValue(unsortMap, DESC); printMap(sortedMapDesc); } private static Map<String, Integer> sortByValue(Map<String, Integer> unsortMap, final boolean order) { List<Entry<String, Integer>> 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<String, Integer> map) { map.forEach((key, value) -> System.out.println("Key :" + key +" Value :" + value)); } } |
假设Java,你可以像这样排序哈希图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public LinkedHashMap<Integer, String> sortHashMapByValues( HashMap<Integer, String> passedMap) { List<Integer> mapKeys = new ArrayList<>(passedMap.keySet()); List<String> mapValues = new ArrayList<>(passedMap.values()); Collections.sort(mapValues); Collections.sort(mapKeys); LinkedHashMap<Integer, String> sortedMap = new LinkedHashMap<>(); Iterator<String> valueIt = mapValues.iterator(); while (valueIt.hasNext()) { String val = valueIt.next(); Iterator<Integer> 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; } |
只是一个开球的例子。这种方法更有用,因为它对哈希图进行排序并保留重复的值。
在Java 8中:
1 2 3 4 5 | Map<Integer, String> sortedMap = unsortedMap.entrySet().stream() .sorted(Entry.comparingByValue()) .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); |
基本上你没有。
有已排序的映射,如
你能为你想做的事情提供更多的背景吗?如果您真的只存储密钥的数字(字符串),那么像
或者,您可以将两个单独的集合封装在一个类中,以便同时更新这两个集合?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package com.naveen.hashmap; import java.util.*; import java.util.Map.Entry; public class SortBasedonValues { /** * @param args */ public static void main(String[] args) { HashMap<String, Integer> hm = new HashMap<String, Integer>(); hm.put("Naveen", 2); hm.put("Santosh", 3); hm.put("Ravi", 4); hm.put("Pramod", 1); Set<Entry<String, Integer>> set = hm.entrySet(); List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>( set); Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } }); for (Entry<String, Integer> entry : list) { System.out.println(entry.getValue()); } } } |
1 2 3 | map.entrySet().stream() .sorted((k1, k2) -> -k1.getValue().compareTo(k2.getValue())) .forEach(k -> System.out.println(k.getKey() +":" + k.getValue())); |
作为一种简单的解决方案,如果只需要一个最终结果,您可以使用temp treemap:
1 2 3 4 |
这将使字符串排序为sortedmap的键。
我扩展了treemap并重写entryset()和values()方法。密钥和值需要具有可比性。
遵循代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public class ValueSortedMap<K extends Comparable, V extends Comparable> extends TreeMap<K, V> { @Override public Set<Entry<K, V>> entrySet() { Set<Entry<K, V>> originalEntries = super.entrySet(); Set<Entry<K, V>> sortedEntry = new TreeSet<Entry<K, V>>(new Comparator<Entry<K, V>>() { @Override public int compare(Entry<K, V> entryA, Entry<K, V> 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<V> values() { Set<V> sortedValues = new TreeSet<>(new Comparator<V>(){ @Override public int compare(V vA, V vB) { return vA.compareTo(vB); } }); sortedValues.addAll(super.values()); return sortedValues; } } |
单元测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class ValueSortedMapTest { @Test public void basicTest() { Map<String, Integer> 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<String, Double> 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()); } } |
找到一个解决方案,但不确定性能,如果地图有大尺寸,正常情况下有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /** * sort HashMap<String, CustomData> by value * CustomData needs to provide compareTo() for comparing CustomData * @param map */ public void sortHashMapByValue(final HashMap<String, CustomData> map) { ArrayList<String> keys = new ArrayList<String>(); keys.addAll(map.keySet()); Collections.sort(keys, new Comparator<String>() { @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()); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package SortedSet; import java.util.*; public class HashMapValueSort { public static void main(String[] args){ final Map<Integer, String> map = new HashMap<Integer,String>(); 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<Map.Entry<Integer, String>> entry = map.entrySet(); final Comparator<Map.Entry<Integer, String>> comparator = new Comparator<Map.Entry<Integer, String>>() { @Override public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) { String value1 = o1.getValue(); String value2 = o2.getValue(); return value1.compareTo(value2); } }; final SortedSet<Map.Entry<Integer, String>> sortedSet = new TreeSet(comparator); sortedSet.addAll(entry); final Map<Integer,String> sortedMap = new LinkedHashMap<Integer, String>(); for(Map.Entry<Integer, String> entry1 : sortedSet ){ sortedMap.put(entry1.getKey(),entry1.getValue()); } System.out.println(sortedMap); } } |
1 2 3 4 5 6 7 8 9 10 11 | public static TreeMap<String, String> sortMap(HashMap<String, String> passedMap, String byParam) { if(byParam.trim().toLowerCase().equalsIgnoreCase("byValue")) { // Altering the (key, value) -> (value, key) HashMap<String, String> newMap = new HashMap<String, String>(); for (Map.Entry<String, String> entry : passedMap.entrySet()) { newMap.put(entry.getValue(), entry.getKey()); } return new TreeMap<String, String>(newMap); } return new TreeMap<String, String>(passedMap); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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<combine> list = new ArrayList<combine>(); HashMap<String, Integer> h = new HashMap<String, Integer>(); h.put("nayanana", 10); h.put("lohith", 5); for (Entry<String, Integer> 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<combine> { 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; } } } |