如何根据键的长度对映射进行排序

huangapple go评论133阅读模式
英文:

how to sort map based on key length

问题

我有这个地图

    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((entry1, entry2) -> {
               int slashes1 = entry1.getKey().length() - entry1.getKey().replace("/", "").length();
               int slashes2 = entry2.getKey().length() - entry2.getKey().replace("/", "").length();
               return Integer.compare(slashes1, slashes2);
           })
           .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                            (oldValue, newValue) -> oldValue, LinkedHashMap::new));

这样做是因为它会基于/的数量进行比较我尝试了自定义比较器但没有获得预期的结果
英文:

I have this map:

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

I would like to sort it as based on the length of the key, for example if the key has less number of "/" then it will be the on top.

Expected output:

./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

So for this, I write like this:

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

It does not give output as expected because it does not compare based on "/". I have tried custom comparator but could not get the expected result.

答案1

得分: 3

仅比较长度时,我们可以在自定义的比较器中使用 Integer.compare。<sup>示例</sup>

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

<hr>

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

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));
英文:

To only compare the lengths, we can use Integer.compare in a custom Comparator. <sup>Demo</sup>

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

Of course, you could also create a TreeMap with this custom Comparator so that new keys will still be ordered correctly.

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

<hr>

In order to compare the number of slashes, we can filter over the characters of both Strings.

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

As Andreas suggested, the comparator can be simplified using .thenComparing:

final NavigableMap&lt;String, String&gt; sortedMap = new TreeMap&lt;&gt;(
Comparator.comparingLong((String s) -&gt; s.chars().filter(c -&gt; c == &#39;/&#39;).count())
.thenComparing(Comparator.naturalOrder()));

Alternatively:

Map&lt;String, String&gt; sortedMap = unsortMap.entrySet().stream()
.sorted((a, b) -&gt; Long.compare(a.getKey().chars().filter(c-&gt;c==&#39;/&#39;).count(), b.getKey().chars().filter(c-&gt;c==&#39;/&#39;).count()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -&gt; oldValue,
LinkedHashMap::new));

huangapple
  • 本文由 发表于 2020年7月26日 23:22:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63102080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定