如何使用分组映射流?

时间:2018-01-08 07:29:43

标签: java mapping java-stream

我有一个很长的孩子。

// ordered by parent.id / child.id
Stream<Child> childStream;

说,

Child(id = 1, parent(id = 1))
Child(id = 2, parent(id = 1))
Child(id = 3, parent(id = 2))
Child(id = 4, parent(id = 2))
Child(id = 5, parent(id = 3))

每个Child都有一个父级。

class Child {
    Parent parent;
}

现在,如何将流映射到Family

的流中
class Family {
    Parent parent;
    List<Child> children;
}

我已经知道Collectors.groupingBy,但是流量很长,将它们全部收集到Map中是不适用的。

2 个答案:

答案 0 :(得分:6)

为了将Child个实例分组到Family个实例,您必须处理Stream,因此需要进行终端操作。您可以使用groupingBy,然后将生成的Map转换为您需要的Stream

Stream<Family> families = 
    childStream.collect(Collectors.groupingBy(Child::getParent))
               .entrySet()
               .stream()
               .map(entry -> new Family(entry.getKey(),entry.getValue()));

这是假设您的Family类有一个Family(Parent parent, List<Child> children)构造函数。

答案 1 :(得分:1)

如果按父(id)排序流,则StreamEx为解决方案。

StreamEx.of(childStream)
        .collapse((a, b) -> a.getParent().getId() == b.getParent().getId(), Collectors.toList())
        .map(cl-> new Family(cl.get(0).getParent(), cl))...;

collapse是比较groupBy的懒惰评估。例如,如果您只想获得前5个家庭,则只会加载前5个家庭中的孩子,而不是全部。

StreamEx.of(childStream)
        .collapse((a, b) -> a.getParent().getId() == b.getParent().getId(), Collectors.toList())
        .map(cl-> new Family(cl.get(0).getParent(), cl))
        .limit(5);