Java-8 Streams: 将 List<{String,List}> 转换为 Map>

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

Java-8 Streams: Convert List<{String,List<String>}> to Map<String, List<String>>

问题

import java.util.*;

class Tag {
    private String tagName;
    private List<String> items;

    // Constructor, getters, and setters
}

public class Main {
    public static void main(String[] args) {
        List<Tag> tagList = Arrays.asList(
            new Tag("popular", Arrays.asList("Item1", "Item2", "Item3", "Item4")),
            new Tag("expensive", Arrays.asList("Item2", "Item4", "Item5")),
            new Tag("mostwanted", Arrays.asList("Item1", "Item2", "Item5"))
        );

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

        for (Tag tag : tagList) {
            for (String item : tag.getItems()) {
                resultMap.computeIfAbsent(item, k -> new ArrayList<>()).add(tag.getTagName());
            }
        }

        System.out.println(resultMap);
    }
}

Note: The code above assumes you have a proper constructor, getters, and setters for the Tag class. Also, please make sure to import the necessary packages (java.util.*) to use the required classes and interfaces.

英文:

I have a Tag class which contains a list of Items

class Tag {

private String tagName
private List&lt;String&gt; items

}

I have a list of Tags in which each tag a list of items

List&lt;Tag&gt; tagList =   [
                       {&quot;tagName&quot;: &quot;popular&quot;, &quot;items&quot;: [&quot;Item1&quot;,&quot;Item2&quot;,&quot;Item3&quot;,&quot;Item4&quot;]},
                       {&quot;tagName&quot;: &quot;expensive&quot; , &quot;items&quot;:  [&quot;Item2&quot;,&quot;Item4&quot;,&quot;Item5&quot;]},
                       {&quot;tagName&quot;: &quot;mostwanted&quot;, &quot;items&quot;:  [&quot;Item1&quot;,&quot;Item2&quot;,&quot;Item5&quot;]}
                      ]

I wan to convert this to a map which have the items as key and tagName as values.

expected output :

{
    &quot;Item1&quot; : [&quot;popular&quot;,&quot;mostwanted&quot;],
    &quot;Item2&quot; : [&quot;popular&quot;,&quot;expensive&quot;,&quot;mostwanted&quot;],
    &quot;Item3&quot; : [&quot;popular&quot;,&quot;mostwanted&quot;],
    &quot;Item4&quot; : [&quot;popular&quot;,&quot;expensive&quot;],
    &quot;Item5&quot; : [&quot;expensive&quot;,&quot;mostwanted&quot;]
}

I tried various combination of stream/faltmap/groupingBy, but I didnt get the expected output. Can you please help. Thanks

答案1

得分: 2

你可以使用 flatMapitems 展开,然后使用 SimpleEntry 创建 itemtagName 的配对。然后使用 groupingByitem 进行分组,将 tagName 映射为 tagName 列表。

Map<String, List<String>> tagMap = tagList.stream()
        .flatMap(t -> t.getItems()
                       .stream()
                       .map(item -> new AbstractMap.SimpleEntry<>(item, t.getTagName())))
        .collect(Collectors.groupingBy(m -> m.getKey(),
            Collectors.mapping(m -> m.getValue(), Collectors.toList())));
英文:

You can flat the items using flatMap then create pair of item and tagName using SimpleEntry. Then grouping by item using groupingBy and map tagName to get list of tagName

Map&lt;String, List&lt;String&gt;&gt; tagMap = tagList.stream()
        .flatMap(t -&gt; t.getItems()
                       .stream()
                       .map(item -&gt; new AbstractMap.SimpleEntry&lt;&gt;(item, t.getTagName())))
        .collect(Collectors.groupingBy(m -&gt; m.getKey(),
            Collectors.mapping(m -&gt; m.getValue(), Collectors.toList())));

答案2

得分: 1

这里是一种使用 [tag:java-8] 中的新特性(如 Map::computeIfPresentMap::computeIfAbsent)的过程化方法,但不使用 [tag:java-stream]:

Map<String, List<String>> map = new HashMap<>();
tagList.forEach(tag -> {
    String tagName = tag.getTagName();
    tag.getItems().forEach(item -> {
        map.computeIfPresent(item, (k, v) -> { v.add(tagName); return v; });
        map.computeIfAbsent(item, k -> new ArrayList<>(Arrays.asList(tagName)));
    });
});

map.forEach((k, v) -> System.out.println(k + " " + v));

如果您想要对这些项从 Item1 排序到 Item5,请使用不同的实现:

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

此外,只要 Item3 仅出现一次,您的预期输出就不匹配:

Item1 [popular, mostwanted]
Item2 [popular, expensive, mostwanted]
Item3 [popular]
Item4 [popular, expensive]
Item5 [expensive, mostwanted]
英文:

Here is a procedural way to go using new features from [tag:java-8] such as Map::computeIfPresent and Map::computeIfAbsent, but without [tag:java-stream]:

Map&lt;String, List&lt;String&gt;&gt; map = new HashMap&lt;&gt;();
    tagList.forEach(tag -&gt; {
        String tagName = tag.getTagName();
        tag.getItems().forEach(item -&gt; {
            map.computeIfPresent(item, (k, v) -&gt; { v.add(tagName); return v; });
            map.computeIfAbsent(item, k -&gt; new ArrayList&lt;&gt;(Arrays.asList(tagName)));
   });
});

map.forEach((k, v) -&gt; System.out.println(k + &quot; &quot; + v));

If you want to sort these items from Item1 to Item5, use the different implementation:

Map&lt;String, List&lt;String&gt;&gt; map = new TreeMap&lt;&gt;();

Moreover, your expected output doesn't match as long as there is only one occurence of Item3:

Item1 [popular, mostwanted]
Item2 [popular, expensive, mostwanted]
Item3 [popular]
Item4 [popular, expensive]
Item5 [expensive, mostwanted]

</details>



huangapple
  • 本文由 发表于 2020年7月24日 21:02:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63074120.html
匿名

发表评论

匿名网友

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

确定