如何根据列表中的元素对HashMap<String,List<String>>进行排序?Java 8

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

How to sort a Hashmap<String, List<String>> according to the elements on the list? Java 8

问题

以下是您要翻译的内容:

I&#39;m trying to sort this in natural order byKey and byValue using lambda expression and Stream Pipe line Java 8:

Map&lt;String, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;();

So, the first part (sorting by natural order) is easy but I am having difficulty with the second part.

The sort should be done by the elements of the list`(List&lt;String&gt;)` and the result looks like:

input:
{E, [G,B,H]}
{C, [E,A,B]}
{A, [M,D,C]}

output:
{A, [C,D,M]}
{C, [A,B,E]}
{E, [B,G,H]}

The first part of the sort byKey is like:

result.entrySet().stream()
    .sorted(Map.Entry.comparingByKey()).forEach(e -&gt; {
        System.out.println(e.getKey() + &quot; &quot; + e.getValue() );
    });

But as I mentioned before I don&#39;t know how exactly do the next step:

result.entrySet().stream()
        .sorted(Map.Entry.comparingByKey()
            .thenComparing((e1,e2) -&gt; e1.getValue().stream().sorted((s1,s2) -&gt; s1.compareTo(s2)))
                )
        .forEach(e -&gt; {
            System.out.println(e.getKey() + &quot; &quot; + e.getValue() );
        });

This lambda expression gave me some compile errors.
Also could you add sources to read about?
英文:

I'm trying to sort this in natural order byKey and byValue using lambda expression and Stream Pipe line Java 8:

Map&lt;String, List&lt;String&gt;&gt; result = new HashMap&lt;&gt;();

So, the first part (sorting by natural order) is easy but I am having difficulty with the second part.

The sort should be done by the elements of the list(List&lt;String&gt;) and the result looks like:

input:
{E, [G,B,H]}
{C, [E,A,B]}
{A, [M,D,C]}
output:
{A, [C,D,M]}
{C, [A,B,E]}
{E, [B,G,H]}

The first part of the sort byKey is like:

result.entrySet().stream()
.sorted(Map.Entry.comparingByKey()).forEach(e -&gt; {
System.out.println(e.getKey() + &quot; &quot; + e.getValue() );
});

But as I mentioned before I don't know how exactly do the next step:

result.entrySet().stream()
.sorted(Map.Entry.comparingByKey()
.thenComparing((e1,e2) -&gt; e1.getValue().stream().sorted((s1,s2) -&gt; s1.compareTo(s2)))
)
.forEach(e -&gt; {
System.out.println(e.getKey() + &quot; &quot; + e.getValue() );
});

This lambda expression gave me some compile errors.
Also could you add sources to read about?

答案1

得分: 1

不能依赖键保持在结果映射中的排序顺序,因为映射本质上是无序的。它可能看起来可以工作,但这取决于键的哈希码和其他映射因素。但对于较大的映射,您不能依赖它。要解决这个问题,您可以指定一个TreeMap,它会维护键的排序顺序作为结果映射,然后使用streams来对列表进行排序。

Map<String, List<String>> map = Map.of("E", List.of("G", "B", "H"), "C",
        List.of("E", "A", "B"), "A", List of("M", "D", "C"));

Map<String, List<String>> result = map.entrySet().stream()
        .collect(Collectors.toMap(Entry::getKey,
                e -> e.getValue().stream().sorted().toList(),
                (a,b)->a, // merge function here, not used but required
                TreeMap::new));

result.entrySet().forEach(System.out::println);

打印结果如下:

A=[C, D, M]
C=[A, B, E]
E=[B, G, H]

与上面的方法的替代方案是基于键对Entry进行排序,然后指定一个LinkedHashMap。LinkedHashMap会保留插入顺序。除此之外,其他都与上面相同。

Map<String, List<String>> result2 = map.entrySet().stream()
.sorted(Entry.comparingByKey())
.collect(Collectors.toMap(Entry::getKey,
        e -> e.getValue().stream().sorted().toList(),
        (a,b)->a,   // merge function here, not used but required
        LinkedHashMap::new));
英文:

You cannot depend on the keys to remain in sorted order in the resulting map since maps are inherently unordered. It may appear to work but it depends on the hashCodes of the keys and other map factors. But for larger maps you cannot depend on it. To solve this you can specify a TreeMap which maintains a sorted order for the keys as then resultant map and use streams to sort the lists.

Map&lt;String, List&lt;String&gt;&gt; map = Map.of(&quot;E&quot;, List.of(&quot;G&quot;, &quot;B&quot;, &quot;H&quot;), &quot;C&quot;,
List.of(&quot;E&quot;, &quot;A&quot;, &quot;B&quot;), &quot;A&quot;, List.of(&quot;M&quot;, &quot;D&quot;, &quot;C&quot;));
Map&lt;String, List&lt;String&gt;&gt; result = map.entrySet().stream()
.collect(Collectors.toMap(Entry::getKey,
e -&gt; e.getValue().stream().sorted().toList(),
(a,b)-&gt;a, // merge function here, not used but required
TreeMap::new));
result.entrySet().forEach(System.out::println);

prints

A=[C, D, M]
C=[A, B, E]
E=[B, G, H]

An alternative to the above is to sort the Entry based on the key and the specify a LinkedHashMap. LinkedHashMaps retain their insertion order. Everything else is the same as above.

Map&lt;String, List&lt;String&gt;&gt; result2 = map.entrySet().stream()
.sorted(Entry.comparingByKey())
.collect(Collectors.toMap(Entry::getKey,
e -&gt; e.getValue().stream().sorted().toList(),
(a,b)-&gt;a,   // merge function here, not used but required
LinkedHashMap::new));
</details>

huangapple
  • 本文由 发表于 2023年2月27日 07:51:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575735.html
匿名

发表评论

匿名网友

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

确定