我有以下方法,用于在数据库中创建订单,order有许多项,item有许多账单。iPadPOSOrderDTO是将基本保存到数据库中的顺序。
因此,用于创建顺序的基于循环的代码如下
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。
所以,我做了以下工作
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进行这种重构,是否有人会分享他们的经验和建议。
发布于 2020-03-13 10:10:03
请注意,这些大小检查并不是真正必要的。空列表将导致空流,因此不会应用任何内容。唯一的好处是您可以避免完全创建流,但我非常怀疑性能差异甚至是显而易见的。
如果要将潜在的空集合转换为流,则可能需要使用小助手函数:
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);。这将在代码中结束,与上面的代码非常相似,并且没有添加任何好处,因为您没有使用返回的流。
发布于 2020-03-13 09:20:30
过滤掉包含空检查的空值。
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调用的,也是反过来的,这是正确的吗?
https://stackoverflow.com/questions/60667550
复制相似问题