首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Java For循环代码重构为使用Java 8流API

将Java For循环代码重构为使用Java 8流API
EN

Stack Overflow用户
提问于 2020-03-13 09:04:25
回答 2查看 279关注 0票数 0

我有以下方法,用于在数据库中创建订单,order有许多项,item有许多账单。iPadPOSOrderDTO是将基本保存到数据库中的顺序。

因此,用于创建顺序的基于循环的代码如下

代码语言:javascript
复制
 private void createNewOrder(IPadPOSOrderDTO iPadPOSOrderDTO) {
    IPadPOSOrderV2 order = mapper.map(iPadPOSOrderDTO, IPadPOSOrderV2.class);
    if(order.getOrderV2Bills()!=null && order.getOrderV2Bills().size()>0){
        for(IPadPOSOrderV2Bill orderBill : order.getOrderV2Bills()){
            orderBill.setOrder(order);

            if(orderBill.getiPadPOSOrderV2BillItems()!=null && orderBill.getiPadPOSOrderV2BillItems().size()>0){
                for(IPadPOSOrderV2BillItems orderBillItem :  orderBill.getiPadPOSOrderV2BillItems()){
                    orderBillItem.setiPadPOSOrderV2Bill(orderBill);
                    orderBillItem.setOrderId(order.getOrderId());

                }
            }
        }
    }

    sessionFactory.
            getCurrentSession().save(order);
}

我想重构上面的代码以使用Java 8 streams API。

所以,我做了以下工作

代码语言:javascript
复制
private void createNewOrderV2(IPadPOSOrderDTO iPadPOSOrderDTO) {
        IPadPOSOrderV2 order = mapper.map(iPadPOSOrderDTO, IPadPOSOrderV2.class);
        if(order.getOrderV2Bills()!=null && order.getOrderV2Bills().size()>0){
            order.getOrderV2Bills().stream().forEach(e -> { createBill(order,e);});
        }
        sessionFactory.
                getCurrentSession().save(order);
    }

    private void createBill(IPadPOSOrderV2 ipadExistingOrderFromDatabase, IPadPOSOrderV2Bill iPadPOSOrderV2Bill) {
        iPadPOSOrderV2Bill.setOrder(ipadExistingOrderFromDatabase);

        if(iPadPOSOrderV2Bill.getiPadPOSOrderV2BillItems()!=null && iPadPOSOrderV2Bill.getiPadPOSOrderV2BillItems().size()>0){
            iPadPOSOrderV2Bill.getiPadPOSOrderV2BillItems().stream().forEach(e -> createBillItem(ipadExistingOrderFromDatabase,iPadPOSOrderV2Bill,e));
        }
    }

    private void createBillItem(IPadPOSOrderV2 ipadExistingOrderFromDatabase, IPadPOSOrderV2Bill iPadPOSOrderV2Bill, IPadPOSOrderV2BillItems iPadPOSOrderV2BillItem) {
        iPadPOSOrderV2BillItem.setiPadPOSOrderV2Bill(iPadPOSOrderV2Bill);
        iPadPOSOrderV2BillItem.setOrderId(ipadExistingOrderFromDatabase.getOrderId());
        ipadExistingOrderFromDatabase.getOrderV2Bills().stream().forEach(e -> { createBill(ipadExistingOrderFromDatabase,e);});
    }

如果我正在正确地使用streams API进行这种重构,是否有人会分享他们的经验和建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-13 10:10:03

请注意,这些大小检查并不是真正必要的。空列表将导致空流,因此不会应用任何内容。唯一的好处是您可以避免完全创建流,但我非常怀疑性能差异甚至是显而易见的。

如果要将潜在的空集合转换为流,则可能需要使用小助手函数:

代码语言:javascript
复制
public <T> Stream<T> collectionToStream(Collection<T> collection) {
  return Optional.ofNullable(collection).map(Collection::stream).orElseGet(Stream::empty);
}

使用forEach(),您可以这样做:

代码语言:javascript
复制
private void createNewOrder(IPadPOSOrderDTO iPadPOSOrderDTO) {
  IPadPOSOrderV2 order = mapper.map(iPadPOSOrderDTO, IPadPOSOrderV2.class);
  collectionToStream(order.getOrderV2Bills()).forEach( orderBill -> {
      orderBill.setOrder(order);

      collectionToStream(orderBill.getiPadPOSOrderV2BillItems()).forEach(orderBillItem -> {
          orderBillItem.setiPadPOSOrderV2Bill(orderBill);
          orderBillItem.setOrderId(order.getOrderId());
        }
      }
    }
  }   

  sessionFactory.getCurrentSession().save(order);
}

请注意,这与初始代码并没有太大的不同,因此您应该考虑一下这种转换是否有意义。

将嵌套的循环转换为完全连续的流将更加困难,而且最终也不会有那么大的不同,因为您不能将orderBill平面映射到orderBillItem流。这样做不会使orderBill在下游可用,因此您必须在返回嵌套流之前调用orderBillItem.setiPadPOSOrderV2Bill(orderBill);。这将在代码中结束,与上面的代码非常相似,并且没有添加任何好处,因为您没有使用返回的流。

票数 1
EN

Stack Overflow用户

发布于 2020-03-13 09:20:30

过滤掉包含空检查的空值。

代码语言:javascript
复制
     private void createNewOrderV2(IPadPOSOrderDTO iPadPOSOrderDTO) {
          IPadPOSOrderV2 order = mapper.map(iPadPOSOrderDTO, IPadPOSOrderV2.class);
          order.getOrderV2Bills().stream().filter(Objects::nonNull).forEach(e -> createBill(order, e));
          sessionFactory.getCurrentSession().save(order);
       }

       private void createBill(IPadPOSOrderV2 ipadExistingOrderFromDatabase, IPadPOSOrderV2Bill iPadPOSOrderV2Bill) {
          iPadPOSOrderV2Bill.setOrder(ipadExistingOrderFromDatabase);
          iPadPOSOrderV2Bill.getiPadPOSOrderV2BillItems().stream().filter(Objects::nonNull).forEach(e -> {
                e.setiPadPOSOrderV2Bill(iPadPOSOrderV2Bill);
                e.setOrderId(ipadExistingOrderFromDatabase.getOrderId());
          });
       }

顺便说一下,createBill()是由createBillItem调用的,也是反过来的,这是正确的吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60667550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档