Рефакторинг Java Для кода l oop для использования Java 8 потоков API - PullRequest
0 голосов
/ 13 марта 2020

У меня есть следующий метод, который используется для создания заказа в базе данных, у заказа много товаров, а у товара много счетов. iPadPOSOrderDTO - это порядок, который будет сохранен в базе данных.

, поэтому код для создания заказа на основе l oop выглядит следующим образом:

 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 потоков API.

Итак, я сделал следующее

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);});
    }

Может кто-нибудь поделиться своим опытом и посоветовать мне, если я правильно использую API потоков для этого рефакторинга.

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Обратите внимание, что эти проверки размера не являются действительно необходимыми. Пустой список приведет к пустому потоку и, следовательно, ничего не будет применено. Единственным преимуществом будет то, что вы сможете избежать создания потока в целом, но я очень сомневаюсь, что разница в производительности будет даже заметной.

Если вы хотите преобразовать потенциально нулевую коллекцию в поток, вы Возможно, вы захотите использовать небольшую вспомогательную функцию:

public <T> Stream<T> collectionToStream(Collection<T> collection) {
  return Optional.ofNullable(collection).map(Collection::stream).orElseGet(Stream::empty);
}

Используя forEach(), вы можете сделать что-то вроде этого:

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); , прежде чем вернет вложенный поток. Это приведет к тому, что код будет очень похож на приведенный выше и не принесет никакой пользы, поскольку вы не используете возвращаемый поток.

0 голосов
/ 13 марта 2020

Отфильтровывать нули, пропуская нулевые проверки

     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, а также наоборот, это правильно?

...