简体   繁体   English

在包含大量空值的对象中导航

[英]Navigate in object with a lot of nulls

I'm trying to implement a good design in my code.我正在尝试在我的代码中实现一个好的设计。 There is a Entity purchaseOrder and I need to navigate inside that object that has a list of stockOrder and each StockOrder has a list of StockOrderItem.有一个实体 purchaseOrder,我需要在具有 stockOrder 列表的对象内部导航,并且每个 StockOrder 都有一个 StockOrderItem 列表。 There is no guarantee that a stockOrder or stockOrderItem exists so I needed to check a lot of nulls.不能保证 stockOrder 或 stockOrderItem 存在,所以我需要检查很多空值。 Is there a elegant way to do that?有没有一种优雅的方法来做到这一点?

        PurchaseOrder purchaseOrder = purchaseOrderRepository.
            findByIdentifierAndBrandId(po.getPurchaseOrderIdentifier(), po.getBrandId());
        List<StockOrder> stockOrders = Optional.ofNullable(
            purchaseOrder.getStockOrders()).orElse(Collections.emptyList());
        for (StockOrder stockOrder : stockOrders) {
            for (StockOrderItem stockOrderItem : Optional.
                ofNullable(stockOrder.getStockOrderItems()).orElse(Collections.emptyList())) {
                InventoryDataLoad inventoryDataload = new InventoryDataLoad();
                inventoryDataload.setSku(stockOrderItem.getSku());
                inventoryDataLoadList.add(inventoryDataload);
            }
        }

It's not a good practice to return nulls for collection fields.为集合字段返回空值不是一个好习惯。 Considering you have access to these classes, return an empty list from the get methods instead:考虑到您可以访问这些类,请从 get 方法返回一个空列表:

StockOrder.java

public List<StockOrderItem> getStockOrderItems() {
    return this.getStockOrderItems != null this.getStockOrderItems ? Collections.emptyList();
}

Or better, as @Ridiculon pointed out in the comments, initialize the collection fields with a new ArrayList() directly.或者更好,正如@Ridiculon 在评论中指出的那样,直接使用new ArrayList()初始化集合字段。

StockOrder.java

private final List<StockOrderItem> stockOrderItems;

public StockOrder() {
   this.stockOrderItems = new ArrayList();
}

With that in place, you can use a more elegant functional approach to populate your list, such as:有了这些,您可以使用更优雅的功能方法来填充您的列表,例如:

List<InventoryDataLoad> inventoryDataLoadList = purchaseOrderRepository
        .findByIdentifierAndBrandId(po.getPurchaseOrderIdentifier(), po.getBrandId())
        .getStockOrders()
        .stream()
        .map(StockOrder::getStockOrderItems)
        .flatMap(Collection::stream)
        .map(item -> {
            InventoryDataLoad inventoryDataload = new InventoryDataLoad();
            inventoryDataload.setSku(item.getSku());
            return inventoryDataload;
        })
        .collect(Collectors.toList());

If you don't have access to the classes to change the get method, you can create your own get methods:如果您无权访问类来更改 get 方法,则可以创建自己的 get 方法:

private List<StockOrderItem> getStockOrderItems(StockOrder stockOrder) {
    return stockOrder.getStockOrderItems() != null ? stockOrder.getStockOrderItems() : Collections.emptyList();
}

private List<StockOrder> getStockOrders(PurchaseOrderRepository purchaseOrderRepository, PurchaseOrder po) {
    List<StockOrder> stockOrders = purchaseOrderRepository
            .findByIdentifierAndBrandId(po.getPurchaseOrderIdentifier(), po.getBrandId())
            .getStockOrders();
    return stockOrders != null ? stockOrders : Collections.emptyList();
}

And then do the functional approach using those:然后使用以下方法执行功能方法:

List<InventoryDataLoad> inventoryDataLoadList = getStockOrders(purchaseOrderRepository, po)
        .stream()
        .map(this::getStockOrderItems)
        .flatMap(Collection::stream)
        .map(item -> {
            InventoryDataLoad inventoryDataload = new InventoryDataLoad();
            inventoryDataload.setSku(item.getSku());
            return inventoryDataload;
        })
        .collect(Collectors.toList());

EDIT: In both cases you can also improve it a little further by creating a separate method for creating the InventoryDataLoad object, such as:编辑:在这两种情况下,您还可以通过创建一个单独的方法来创建InventoryDataLoad对象来进一步改进它,例如:

private InventoryDataLoad createInventoryDataLoad(StockOrderItem item) {
    InventoryDataLoad inventoryDataload = new InventoryDataLoad();
                inventoryDataload.setSku(item.getSku());
                return inventoryDataload;
}

And then:接着:

List<InventoryDataLoad> inventoryDataLoadList = getStockOrders(purchaseOrderRepository, po)
        .stream()
        .map(this::getStockOrderItems)
        .flatMap(Collection::stream)
        .map(this::createInventoryDataLoad)
        .collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM