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

6 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)

    }
}
Run Code Online (Sandbox Code Playgroud)

有没有明确的方法来处理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
}
Run Code Online (Sandbox Code Playgroud)

Nam*_*man 10

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

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


Ste*_*n C 2

如果您正在寻找最有效的方法来执行此操作,请坚持使用当前的方法。您的解决方案很冗长,但可能尽可能有效。毫无疑问,您的代码比其他替代方案更容易理解。

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


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


另外,我想每次检查 null 是否比添加到列表并迭代它更昂贵?

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


最后要注意的一件事是,这样的代码的效率通常并不重要。我们讨论的可能是不到 100 条指令的差异;即小于 1 微秒的差异。与应用程序正在执行的其他操作相比,这可能是微不足道的。