簡體   English   中英

有沒有更好的方法來處理 Java 中的多個空檢查?

[英]Is there a better way of handling multiple null checks in Java?

我有以下代碼

Set<Product> getallProducts(){

    Product p = getProduct(brand, price);
    Product p1 = getProduct(brand, price, location);
    Product p2 = getProduct(brand, price, qty);

   Set<SuperProducts> superProducts = new HashSet<>;


   if(p!=null){
      SuperProduct sp  = getSuperProduct(p)
      superProducts.add(sp)
   }

   if(p1!=null){
      SuperProduct sp1  = getSuperProduct(p1)
      superProducts.add(sp)

   }

   if(p2!=null){
      SuperProduct sp2  = getSuperProduct(p2)
      superProducts.add(sp2)

    }
}

有沒有明確的方法來處理 p!=null, p2!=null, p1 !=null。 我可以將 p,p1,p2 添加到列表中並按如下方式遍歷它,但我正在尋找一種比將產品添加到列表然后遍歷它們更便宜的方法。? 另外,我想知道每次檢查 null 是否比添加到列表並遍歷它更昂貴?

List<Product> products = new ArrayList<>():
products.add(p);
products.add(p1);
products.add(p2);

and 
for(Product p:products){
// and adding to superProducts
}

您可以使用Stream.of然后filter為:

return Stream.of(p1, p2, p3).filter(Objects::nonNull)
                            .map(this::getSuperProduct)
                            .collect(Collectors.toSet());

這是一種使用 Optional 的方法,不會比其他答案長多少,因為無論如何都需要創建每個 Product 對象。

Set<Product> getallProducts() {
    Set<SuperProducts> superProducts = new HashSet<>;

    Optional.ofNullable(getProduct(brand, price))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));
    Optional.ofNullable(getProduct(brand, price, location))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));
    Optional.ofNullable(getProduct(brand, price, qty))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));

    return superProducts;
}

如果您正在尋找執行此操作的最佳方式,請堅持使用您當前的方式。 您的解決方案很冗長,但可能盡可能有效。 毫無疑問,您的代碼比其他替代方案更容易理解。

如果您正在尋找使用更少代碼行的解決方案,您可以使用流和過濾器來實現這一點,或者通過創建Product引用和迭代的數組或列表來實現。 然而,這些解決方案都需要創建臨時數據結構並且效率大大降低。


請注意,如果getSuperProduct(p)調用是由 JIT 編譯器內聯的,那么它可能能夠優化掉調用中發生的null隱式測試。


另外,我想知道每次檢查 null 是否比添加到列表並遍歷它更昂貴?

我想你會發現情況正好相反。 在任何一種情況下,您都需要進行空檢查(或不...見上文)。 當你嘗試使用一個列表、數組或流時,你有創建數據結構的開銷(一個或多個新的堆對象來創建和初始化),當你到達列表的末尾時你有測試的開銷/陣列/流。


最后要注意的一件事是,像這樣的代碼的效率通常是無關緊要的。 我們可能在談論不到 100 條指令的差異; 即小於 1 微秒的差異。 與應用程序正在執行的其他操作相比,這可能是微不足道的。

鑒於相同的代碼序列重復 3 次,我將編寫一個實用方法:

 private void addSuper(Product p, Set<SuperProduct> s) {
   if (p != null)
      s.add(getSuperProduct(p));
 }

進而

Set<SuperProduct> superProducts = new HashSet<>();
addSuper(getProduct(brand, price), superProducts);
addSuper(getProduct(brand, price, location), superProducts);
addSuper(getProduct(brand, price, qty), superProducts);

我在進行這種重構時主要關注的不是“非空測試”,而是原始內容的重復性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM