Flatten List<A> 其中每个 A 包含一个 List<B> 用于每个不同的 B

Flatten List<A> where each A contains a List<B> for every distinct B

我的目标是扩展 List<A>,其中每个 A 都有一个属性 List<B>List<A>,其中每个 A 将包含一个列表有一个不同的对象 B.

考虑到 AB 具有以下结构:

class A{
  String idA;
  List<B> listOfB;
}

class B{
  Long idB;
  String name;
}

我想扩展 List<A> 以便它为每个不同的包含对象 B 包含一个对象 A(其中两个对象 B 由属性 name)。 例如

[
  {
    "idA": 1,
    "listOfB": [
      {
        "idB": 3,
        "name": "Foo"
      }
    ]
  },
  {
    "idA": 2,
    "listOfB": [
      {
        "idB": 3,
        "name": "Foo"
      },
      {
        "idB": 4,
        "name": "Bar"
      }
    ]
  }
]

应该改成

  {
    "idA": 1,
    "listOfB": [
      {
        "idB": 3,
        "name": "Foo"
      }
    ]
  },
  {
    "idA": 2,
    "listOfB": [
      {
        "idB": 3,
        "name": "Foo"
      }
    ]
  },
  {
    "idA": 2,
    "listOfB": [
      {
        "idB": 4,
        "name": "Bar"
      }
    ]
  }
]

如何使用 streams 执行此操作?

如果您在 B 中实现 equals,这可能是解决方案之一。

        Set<B> bs = as.stream()
                .map(A::getListOfB)
                .flatMap(List::stream)
                .collect(Collectors.toSet());

        return bs.stream()
                .map(s -> as.stream()
                        .filter(a -> a.getListOfB().contains(s))
                        .map(a -> new A(a.idA, List.of(s)))
                        .collect(Collectors.toList())
                )
                .flatMap(List::stream)
                .collect(Collectors.toList());

请注意,我已经在 A 和 B 中创建了所有参数构造函数。

如果我正确理解了您提供的解释和示例,您需要构建一个由对象 A 组成的结果列表,其中每个元素将包含对列表的引用,其中一个元素类型为 B.

A singleton-list 和一个新对象 A 必须为最初包含在特定对象 A 中的每个不同对象 B 创建将保存此列表的新对象 A

为此,您可以使用 flatMap() 操作,该操作接受一个元素和 returns 扁平元素流。在嵌套流中应用的操作 distinct() 将确保只有唯一对象 B 将从每个列表中被窥视(我假设 hashCode/equals 合同在 class B).

List<A> listB = getSourceList();

listB.stream()
        .flatMap(a -> a.getListOfB().stream()
                  .distinct()
                  .map(b -> new A(a.getIdA(), List.of(b))))
        .collect(Collectors.toList());