首页 > 解决方案 > 是否可以在 java 8 中的不同对象流上执行平面映射时合并列表属性?

问题描述

我有一个流操作并没有完全按照我的意愿去做

鉴于这种数据结构

CatOwner {
    id, 
    name, 
    List <CatType>
}           

这段代码

    List<CatOwner> catOwner = owners.stream()
               .map(CatOwnerAccount:getCatOwnerAccountDetails)
               .filter(Objects::nonNull)
               .flatMap(catOwnerFunction)
               .distinct()
               .collect(Collectors.toList());

在哪里

Function<CatOwnerAccountDetails, Stream<CatOwner>> catOwnerFunction = catOwnerDetails -> getCatOwners(catOwnerDetails);

我希望这给我一个合并的唯一所有者列表,将他们所有来自不同来源的猫组合起来,所以不是产生这个(因为它是平面映射,然后对具有不同列表的对象进行不同的处理)它会合并列表

所以而不是生产这个

{ id : 1, name: Steve, cattype : [tabby, ginger] }
{ id : 1, name: Steve, cattype : [black] }
{ id : 2, name: Mandy, cattype : [tortashelle] }
{ id : 2, name: Mandy, cattype : [manx, grey] }

它会产生这个

{ id : 1, name: Steve, cattype : [tabby, ginger, black] }
{ id : 2, name: Mandy, cattype : [tortashelle, manx, grey]  }

任何人都可以帮忙吗?

标签: javajava-8

解决方案


您可以通过创建中间地图来做到这一点,但它不是很漂亮。

Collection<CatOwner> values = owners.stream()
    // blah blah, the other stuff you had
    .collect(
        Collectors.toMap(
            owner -> new Pair<>(owner.getId(), owner.getName()),
            Function.identity(),
            (a, b) -> {
                a.getTypes().addAll(b.getTypes());
                return a;
            }
        )
    )
    .values();

我使用 ajavafx.util.Pair作为键,尽管任何实现相等作为两个元素的组合相等的元组类都可以。

owner -> new Pair<>(owner.getId(), owner.getName())

这表示地图的值是CatOwner项目本身(即地图是Pair<Id, Name>to CatOwner)。

Function.identity()

这表示如果发生冲突(具有相同 ID 和名称的两个项目),解决该问题的方法是将所有类型从一个添加CatOwner到另一个。

(a, b) -> {
    a.getTypes().addAll(b.getTypes());
    return a;
}

结果是 a Collection,因为您获取了地图的所有值。如果您真的想要/需要一个列表,您可以将这些值添加到一个新列表中。

new ArrayList<>(values);

推荐阅读