如何流式传输和映射一对多关系?

时间:2017-03-21 23:29:07

标签: java collections java-8 java-stream

说我有以下两个对象:

public class MasterObject {
  Long masterId;
  Long detailId;
  String attribute1;
  //...
}

public class DetailObject {
  Long detailId;
  String attribute2;
  //..
}

我有一个包含10个主对象的超集列表,以及2个详细对象的子集列表。最后,在我验证了attribute1 == attribute2之后,我需要一组新的10个详细信息对象(从主设备复制信息),并带有相应的详细信息ID。对于每个细节对象,我需要创建一个新的主对象。这是我到目前为止所提出的,但这是不正确的。请注意我的评论栏:

List<DetailObject> updatedDetails = masterObjects.stream()
  .filter(master -> {
    return detail.stream()
      .anyMatch(it -> master.getAttribute1() == detail.getAttribute2());
  })
  .map(master -> {
    DetailObject detailObject = new DetailObject();
    // Here is where I thought I could set the master Id in the detail object,
    // but I no longer have access to the original detail stream
     return detailObject;
   })
  .collect(Collectors.toList());

我很确定我需要在过滤器之后做一些事情,但当我需要对象本身时,过滤器当然只返回一个布尔值。该怎么办?

2 个答案:

答案 0 :(得分:3)

我真的不了解你的策略。特别是,根本没有修改DetailObject的masterId的指令,并且您正在创建新的DetailObject实例,尽管我没有看到任何理由这样做。

此外,您将字符串与==进行比较。

为什么不循环查看详细信息,对于每个细节,找到具有相同属性的master,如果找到,更新详细信息的masterId?

details.forEach(
    d -> masters.stream() 
                .filter(m -> m.getAttribute1().equals(d.getAttribute2()))
                .findAny()
                .ifPresent(m -> d.setMasterId(m.masterId)));

这是O(m * n),但是对于m和n为2和10,它确实无关紧要。

您也可以使用循环:

for (Master m : masters) {
    for (Detail d : details) {
        if (m.getAttribute1().equals(d.getAttribute2())) {
            d.setMasterId(m.getMasterId());
            break;
        }
    }
}

答案 1 :(得分:1)

我&amp;我的同事找到了我的问题的解决方案。它看起来像这样:

List<DetailObject> newDetails = details.stream()
  .map(detail -> {
    return masters.stream()
      .filter(master -> filterLoans(detail, master))
      .map(master -> createDetail(detail, master))
      .collect(Collectors.toList());
  })
  .flatMap(List::stream)
  .collect(Collectors.toList());