Java 8:将具有字符串值的映射转换为包含不同类型的列表

Posted

技术标签:

【中文标题】Java 8:将具有字符串值的映射转换为包含不同类型的列表【英文标题】:Java 8: Convert a map with string values to a list containg a different type 【发布时间】:2016-02-29 14:36:17 【问题描述】:

我有这个Map

Map<Integer, Set<String>> map = ...

我有这门课Foo:

class Foo 
    int id;
    String name;

我想将地图转换为List&lt;Foo&gt;。 Java 8 中是否有方便的方式来执行此操作?

目前,我的方式是:

List<Foo> list = new ArrayList<>((int) map.values().flatMap(e->e.stream()).count()));

for(Integer id : map.keySet())
    for(String name : map.get(id))
        Foo foo = new Foo(id,name);
        list.add(foo);  
    

我觉得太麻烦了。

【问题讨论】:

How to convert a Map to List in Java?的可能重复 不,它不是重复的。 @zhugowei 我必须同意你的观点。我已经编辑了问题以防止误解。 【参考方案1】:

你的版本比较麻烦的主要原因是你决定先计算ArrayList的容量。由于此计算需要遍历整个地图,因此不太可能有任何好处。你绝对不应该做这样的事情,除非你已经使用适当的基准证明它是必要的。

我看不出仅使用您的原始版本但使用ArrayList 的无参数构造函数有什么问题。如果你还去掉了多余的局部变量foo,它实际上比流版本的字符更少(并且更清晰)。

【讨论】:

是的,你是对的。但是不优化很难忍住【参考方案2】:
final Map<Integer, Set<String>> map = new HashMap<>();

map
    .entrySet()
    .stream()
    .flatMap(e -> e.getValue().stream().map(s -> new Foo(e.getKey(), s)))
    .collect(Collectors.toList());

【讨论】:

【参考方案3】:

您可以拥有以下内容:

List<Foo> list = map.entrySet()
                    .stream()
                    .flatMap(e -> e.getValue().stream().map(name -> new Foo(e.getKey(), name)))
                    .collect(toList());

对于映射的每个条目,我们创建一个值的 Stream 并将其映射到对应的 Foo,然后使用 flatMap 将其展平。

【讨论】:

以上是关于Java 8:将具有字符串值的映射转换为包含不同类型的列表的主要内容,如果未能解决你的问题,请参考以下文章

将包含字符串键/值的文件转换为Go映射

从字符串转换为具有大量值的 Java 枚举 [重复]

Pandas Dataframe 将具有两个值的分类列重新映射为二进制

如何将具有十进制值的数字转换为PL / SQL中的浮点数?

将对象列表转换为映射Java 8流

如何将包含逗号分隔的 json 值的单个字符串转换为单个 json 对象?