Java流将地图类属性列表转换为扁平化地图

时间:2019-03-13 19:28:22

标签: java java-stream

如何通过使用Java流以最佳方式将List 转向Map >。

当心:propertyA不是唯一的

//pseudo-code
class Foo
    propertyA //not unique
    List<propertyB>

到目前为止,我有以下内容:

fooList.stream()
       .collect(Collectors.groupingBy(Foo::propertyA, 
                    Collectors.mapping(Foo::propertyB, Collectors.toList())))

产生Map<propretyA, List<List<propretyB>>>,但尚未对其值进行展平。

3 个答案:

答案 0 :(得分:5)

您可以使用Java 9+ Collectors.flatMapping

Map<propretyA, List<propretyB>> result = fooList.stream()
       .collect(Collectors.groupingBy(Foo::propertyA, 
                Collectors.flatMapping(foo -> foo.propertyB().stream(), 
                                       Collectors.toList())));

另一种方法(Java8 +)是使用this answer中的Collectors.toMap

Java8 +的另一种方法是不使用流,而是使用Map.computeIfAbsent

Map<propretyA, List<propretyB>> result = new LinkedHashMap<>();
fooList.forEach(foo -> result.computeIfAbsent(foo.propertyA(), k -> new ArrayList<>())
                             .addAll(foo.propertyB()));

答案 1 :(得分:4)

这应该做到:

    fooList.stream()
           .collect(Collectors.toMap(Foo::getPropertyA, Foo::getPropertyBList, (l1, l2) -> {
               l1.addAll(l2);
               return l1;
           }));

答案 2 :(得分:1)

您可以将Collectors.toMap与合并功能一起使用,在复制键时必须决定必须使用哪个List<propertyB>

Map<propertyA, List<propertyB>> collect = list.stream()
        .collect(Collectors.toMap(Foo::getPropertyA, Foo::getList, (l1, l2) -> ???));

否则,您可以获得IllegalStateException。来自javadoc

  

如果映射的键包含重复项(根据Object.equals(Object)),则执行收集操作时将抛出IllegalStateException。

由您决定如何实现合并功能,但是通常您只想返回2个列表的并集,例如:l1.addAll(l2); return l1;