有没有更好的方法来处理Java中的多个空检查?

时间:2019-05-12 13:49:34

标签: java java-8

我有以下代码

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
}

4 个答案:

答案 0 :(得分:10)

您可以先选择Stream.of,然后再选择filter

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

答案 1 :(得分:2)

这里是使用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;
}

答案 2 :(得分:2)

鉴于相同的代码序列重复了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);

我进行此重构的主要关注点不是“非空测试”,而是原始代码的重复性质。

答案 3 :(得分:1)

如果您正在寻找最高效的方法,请坚持目前的操作方式。您的解决方案很冗长,但可能会尽可能高效。毫无疑问,您的代码比其他方法更易于理解。

如果您正在寻找使用更少代码行的解决方案,则可以使用流和过滤器,或者通过创建Product引用的数组或列表并进行迭代来实现此目的。但是,这些解决方案都需要创建临时数据结构,并且效率大大降低。


请注意,如果JIT编译器内联了getSuperProduct(p)调用,则它可能能够优化调用中发生的null的隐式测试。


  

此外,我想每次检查null是否比添加到列表并遍历它昂贵吗?

我认为您会发现相反的情况。无论哪种情况,您都需要进行null检查(或不进行...参见上文)。当您尝试使用列表,数组或流时,您将需要创建数据结构(创建或初始化一个或多个新堆对象)的开销,并且在到达列表末尾时要进行测试的开销/ array / stream。


最后要注意的一点是,这样的代码效率通常并不重要。我们可能正在谈论少于100条指令的差异;即小于1微秒的差异。与应用程序其余部分相比,它可能微不足道。