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

时间:2015-11-26 13:12:44

标签: java java-8 java-stream map-function

我有Map

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

我有这个课程Foo

class Foo {
    int id;
    String name;
}

我想将地图转换为List<Foo>。在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);  
    }
}

我觉得这太麻烦了。

3 个答案:

答案 0 :(得分:6)

您可以拥有以下内容:

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

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

答案 1 :(得分:2)

您的版本繁琐的主要原因是您已决定首先计算ArrayList的容量。由于此计算需要迭代整个地图,因此不太可能有任何好处。除非你已经证明使用了需要的适当基准,否则你绝对不应该做这样的事情。

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

答案 2 :(得分:0)

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