如何根据密钥长度对地图进行排序

时间:2020-07-26 15:22:08

标签: java sorting java-stream

我有这张地图:

Map < String, String > unsortMap = new HashMap < String, String > ();
unsortMap.put("./cq:dialog/content/items/tabs/items/tab1/items/columns/items", "40");
unsortMap.put("./cq:dialog/content", "80");
unsortMap.put("./cq:dialog", "75");
unsortMap.put("./cq:dialog/content/items/tabs/items/tab2/items/columns/items", "40");
unsortMap.put("./cq:dialog/content/sling:resourcetype", "granite/ui/components/coral/foundation/container");

我想根据键的长度对它进行排序,例如,如果键的“ /”数量较少,那么它将排在最前面。

预期输出:

./cq:dialog
./cq:dialog/content/
./cq:dialog/content/sling:resourcetype
./cq:dialog/content/items/tabs/items/tab1/items/columns/items
./cq:dialog/content/items/tabs/items/tab2/items/columns/items
  

为此,我这样写:

Map<String, String> sortedMap = unsortMap.entrySet().stream()
       .sorted(Map.Entry.comparingByKey())
       .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (oldValue, newValue) -> oldValue, LinkedHashMap::new));

由于未根据“ /”进行比较,因此未提供预期的输出。我已经尝试过自定义比较器,但无法获得预期的结果。

1 个答案:

答案 0 :(得分:3)

仅比较长度,我们可以在自定义比较器中使用Integer.compare Demo

Map<String, String> sortedMap = unsortMap.entrySet().stream()
        .sorted((a, b) -> Integer.compare(a.getKey().length(), b.getKey().length()))
     .collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));

当然,您也可以使用此自定义比较器创建一个TreeMap,以便仍然可以正确订购新密钥。

final NavigableMap<String, String> sortedMap = new TreeMap<>(
        (a, b) -> a.length() != b.length() ? Integer.compare(a.length(), b.length()) : a.compareTo(b));
sortedMap.putAll(unsortMap);

为了比较斜杠的数量,我们可以过滤两个字符串的字符。

final NavigableMap<String, String> sortedMap = new TreeMap<>((a, b) -> {
    final long slashes1 = a.chars().filter(c -> c == '/').count();
    final long slashes2 = b.chars().filter(c -> c == '/').count();
    return slashes1 != slashes2 ? Long.compare(slashes1, slashes2) : a.compareTo(b);
});
sortedMap.putAll(unsortMap);

如Andreas所建议,可以使用.thenComparing简化比较器:

final NavigableMap<String, String> sortedMap = new TreeMap<>(
        Comparator.comparingLong((String s) -> s.chars().filter(c -> c == '/').count())
         .thenComparing(Comparator.naturalOrder()));

或者:

Map<String, String> sortedMap = unsortMap.entrySet().stream()
        .sorted((a, b) -> Long.compare(a.getKey().chars().filter(c->c=='/').count(), b.getKey().chars().filter(c->c=='/').count()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                LinkedHashMap::new));
相关问题