【问题标题】:How can I sort a Map based upon on the size of its Collection values?如何根据集合值的大小对地图进行排序?
【发布时间】:2015-08-31 10:01:45
【问题描述】:

我有一个这样的HashMap

Map<String, List<String>> map = new HashMap<>();

map.put("USA", Arrays.asList("CA","IA","IL"));
map.put("India", Arrays.asList("MUM","CAL"));
map.put("Canada", Arrays.asList("TOR"));

我想根据列表值的大小按升序对地图进行排序。我该怎么做?

在这种情况下,我想订购加拿大、印度、美国的钥匙。

【问题讨论】:

  • 您不能对 HashMap 进行排序,因为 HashMap 不支持排序。如果要对它们进行排序,则必须将它们放入支持排序的数据结构(即 List、LinkedHashMap)中。

标签: java sorting java-8 java-stream


【解决方案1】:

public static <K,V extends Collection> Map<K,V> sortMap(Map<K,V> map){
        return map.entrySet().stream()
                .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    }

【讨论】:

    【解决方案2】:

    您可以简单地将哈希映射到 Pair() 列表,然后对列表进行排序

    val map: MutableMap<String, List<String>> = HashMap()
    
    map["USA"] = listOf("CA", "IA", "IL")
    map["India"] = listOf("MUM", "CAL")
    map["Canada"] = listOf("TOR")
    
    val sortedPairs = map.map { Pair(it.key, it.value) }.sortedBy { it.second.size }.toMap()
    
    println("sorted List: $sortedPairs")
    

    【讨论】:

      【解决方案3】:

      HashMap 没有保证的迭代顺序,因此您需要收集到 LinkedHashMap 才能使排序有意义。

      import static java.util.Comparator.comparingInt;
      import static java.util.stream.Collectors.toMap;
      
      Map<String, List<String>> sorted = map.entrySet().stream()
          .sorted(comparingInt(e -> e.getValue().size()))
          .collect(toMap(
              Map.Entry::getKey,
              Map.Entry::getValue,
              (a, b) -> { throw new AssertionError(); },
              LinkedHashMap::new
          )); 
      

      AssertionError 被抛出,因为我们没有使用组合函数 only used on parallel streams

      如果您觉得comparingByValue 更具可读性,您也可以使用它:

      import static java.util.Map.Entry.comparingByValue;
      
      Map<String, List<String>> sorted = map.entrySet().stream()
          .sorted(comparingByValue(comparingInt(List::size)))
          // ... as above
      

      【讨论】:

      • @JGFMK import static java.util.Comparator.comparingInt;
      • 第一个代码很有效。后者没有。此外,如果您想要大小递减,请使用 ....................................(e -&gt; -e.getValue().size())comparingInt。您可以在这里看到后者不存在:code.sololearn.com/ccz02MbYMYs1/#java [给出 2 个编译错误:1) 找不到用于 compareByValue 的符号 2) 参数不匹配;无效的方法引用]
      • 啊,是的,我没有指定import static java.util.Map.Entry.comparingByValue; 很好,我会修复它
      • 那还是不行。又进了一点。 code.sololearn.com/cJPV8XUUW9ce/#java 错误:不兼容的类型:Stream>> 无法转换为 Map> .sorted(comparingByValue(comparingInt(List::size))); ^
      • 您不能将流分配给地图。如果要制作地图,则必须像第一个示例一样使用collect(toMap(...))。有人编辑了原始答案并删除了comparingbyValue(comparingInt(..)) 只是comparingInt(e -&gt; ...) 的替代品的解释。我会尽量找时间回滚他们的编辑并解决这个问题。
      【解决方案4】:

      你有两个问题。

      1. 地图不支持排序。

      2. SortedMap 不支持仅对键进行排序的值排序。

      因此,使用 Map 或 SortedMap 对您没有帮助。您需要做的是遍历您的地图并将每个Entry&lt;String, ArrayList&lt;String&gt;&gt; 放入一个集合(如列表)中,然后使用自定义比较对列表进行排序。请参阅此示例 TreeMap sort by value 或此示例 Sorting LinkedHashMap

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-11
        • 2013-10-31
        • 2015-11-07
        • 1970-01-01
        • 2014-08-29
        • 1970-01-01
        相关资源
        最近更新 更多