按值排序HashMap

pro*_*ack 122 java sorting hashmap

我需要HashMap根据存储在其中的值对我进行排序.在HashMap包含存储在手机联系人的名字.

此外,我需要在对值进行排序时自动对键进行排序,或者您可以说键和值绑定在一起,因此值的任何更改都应该反映在键中.

HashMap<Integer,String> map = new HashMap<Integer,String>();
map.put(1,"froyo");
map.put(2,"abby");
map.put(3,"denver");
map.put(4,"frost");
map.put(5,"daisy");
Run Code Online (Sandbox Code Playgroud)

所需输出:

2,abby;
5,daisy;
3,denver;
4,frost;
1,froyo;
Run Code Online (Sandbox Code Playgroud)

Rai*_*lam 160

尝试以下代码,它对我来说很好.您既可以选择升序也可以选择降序

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:版本2

使用了新的java功能,例如stream for-each等

如果值相同,则将按键对映射进行排序

 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));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,使用集合utils以适当的方式编写它. (4认同)
  • 尝试我的问题,发现需要稍微修改比较器逻辑,在那里你不检查应该添加的空检查,因为map值可以包含null元素. (2认同)
  • 有用而明确的答案. (2认同)

San*_*hak 86

假设Java,你可以像这样排序hashmap:

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;
}
Run Code Online (Sandbox Code Playgroud)

只是一个启动的例子.这种方式更有用,因为它对HashMap进行排序并保留重复值.

  • 请注意,由于在两个while循环中重复查找值,给定算法的时间复杂度为O(n ^ 2).将条目集转换为列表,然后基于比较器对List进行排序将是一种更有效的解决方案. (18认同)

Vit*_*nko 62

在Java 8中:

Map<Integer, String> sortedMap = 
     unsortedMap.entrySet().stream()
    .sorted(Entry.comparingByValue())
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                              (e1, e2) -> e1, LinkedHashMap::new));
Run Code Online (Sandbox Code Playgroud)

  • 而这种编程正是我讨厌jdk8的原因。getKey,getValue, (e1,e2)-&gt;e1, ::new... 然后我们可以在火周围召唤“wooloh loh”并召唤夜之灵... (6认同)
  • @AquariusPower 你不需要强制转换,只要给编译器一个关于什么是泛型类型的提示:`Entry.&lt;Integer, String&gt;comparingByValue().reversed()` (4认同)
  • @AquariusPower请参阅https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#reversed中的`reversed`方法 - 您可以将它应用于`comparisonByValue返回的比较器( )` (2认同)
  • 返回`Entry.comparingByValue().reversed()`与`.sorted(...)`期望的params :(,我最终得到一个反向循环`for` over` .trytry().toArray( )`,可能是一个演员可以解决它,我需要更多的时间来测试:) (2认同)

Jon*_*eet 25

你基本上没有.A HashMap基本上是无序的.你的任何模式可能会在排序看应该不会被依靠.

有分类的地图,例如TreeMap,但它们传统上按键而不是值排序.按值排序相对不常见 - 特别是因为多个键可以具有相同的值.

你能为你想做的事情提供更多背景吗?如果你真的只存储号码(字符串)的钥匙,也许是SortedSetTreeSet会为你工作?

或者,您可以存储封装在单个类中的两个单独的集合,以同时更新两个集合?


小智 15

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

        }

    }
}
Run Code Online (Sandbox Code Playgroud)


kol*_*seg 9

作为一种简单的解决方案,如果只需要最终结果,可以使用temp TreeMap:

TreeMap<String, Integer> sortedMap = new TreeMap<String, Integer>();
for (Map.Entry entry : map.entrySet()) {
    sortedMap.put((String) entry.getValue(), (Integer)entry.getKey());
}
Run Code Online (Sandbox Code Playgroud)

这将使您将字符串排序为sortedMap的键.

  • 这仅在所有整数值都是唯一的情况下有效 - 否则,您将覆盖字符串. (16认同)

小智 9

map.entrySet().stream()
                .sorted((k1, k2) -> -k1.getValue().compareTo(k2.getValue()))
                .forEach(k -> System.out.println(k.getKey() + ": " + k.getValue()));
Run Code Online (Sandbox Code Playgroud)

  • 对我来说最易读的解决方案并完成工作,例如运行按值排序的 HashMap (2认同)

Wen*_*del 5

我扩展了一个 TreeMap 并覆盖了 entrySet() 和 values() 方法。键和值需要是可比较的。

按照代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

单元测试:

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());
    }

}
Run Code Online (Sandbox Code Playgroud)