简体   繁体   English

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

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

I have below code我有以下代码

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)

    }
}

Is there a clear way to handle p!=null, p2!=null, p1 !=null.有没有明确的方法来处理 p!=null, p2!=null, p1 !=null。 I can add p,p1,p2 to a list and iterate through it as below but I was looking for a cheaper way than adding products to list and then iterating through them.?我可以将 p,p1,p2 添加到列表中并按如下方式遍历它,但我正在寻找一种比将产品添加到列表然后遍历它们更便宜的方法。? Also, I would like to if checking for null each time is expensive than adding to list and iterating through it?另外,我想知道每次检查 null 是否比添加到列表并遍历它更昂贵?

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

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

You can go for a Stream.of and then filter as:您可以使用Stream.of然后filter为:

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

Here is a way to do it using Optional, not much longer than other answers since each Product object needs to be created anyway.这是一种使用 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;
}

If you are looking for the most performant way of doing this, stick with the way that your are currently doing it.如果您正在寻找执行此操作的最佳方式,请坚持使用您当前的方式。 Your solution is verbose, but probably as efficient as it can be.您的解决方案很冗长,但可能尽可能有效。 And there is no doubt that your code is easier to understand than the other alternatives.毫无疑问,您的代码比其他替代方案更容易理解。

If you are looking for solutions that use fewer lines of code, you can implement this using streams and filters, or by creating an array or list of the Product references and iterating.如果您正在寻找使用更少代码行的解决方案,您可以使用流和过滤器来实现这一点,或者通过创建Product引用和迭代的数组或列表来实现。 However, these solutions all entail creating temporary data structures and are substantially less efficient.然而,这些解决方案都需要创建临时数据结构并且效率大大降低。


Note that if the getSuperProduct(p) call is inlined by the JIT compiler, then it may be able to optimize away the implicit test for null that occurs in the call.请注意,如果getSuperProduct(p)调用是由 JIT 编译器内联的,那么它可能能够优化掉调用中发生的null隐式测试。


Also, I would like to if checking for null each time is expensive than adding to list and iterating through it?另外,我想知道每次检查 null 是否比添加到列表并遍历它更昂贵?

I think that you will find the reverse is the case.我想你会发现情况正好相反。 You will need to do the null checks in either case (or not ... see above).在任何一种情况下,您都需要进行空检查(或不...见上文)。 When you try to use a list, array or stream, you have the overhead of creating the data structure (one or more new heap objects to create and initialize), and you have overhead of testing when you have gotten to the end of the list/array/stream.当你尝试使用一个列表、数组或流时,你有创建数据结构的开销(一个或多个新的堆对象来创建和初始化),当你到达列表的末尾时你有测试的开销/阵列/流。


One final thing to note is that the efficiency of code like this is often immaterial.最后要注意的一件事是,像这样的代码的效率通常是无关紧要的。 We are probably talking about a difference of a less than 100 instructions;我们可能在谈论不到 100 条指令的差异; ie less than 1 microsecond difference.即小于 1 微秒的差异。 It is probably trivial compared with the rest of what the application is doing.与应用程序正在执行的其他操作相比,这可能是微不足道的。

Given that the same code sequence is repeated 3 times, I'd write a utility method:鉴于相同的代码序列重复 3 次,我将编写一个实用方法:

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

and then进而

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

My main concern in doing this refactoring is not the 'test for non-null' but the repetitive nature of the original.我在进行这种重构时主要关注的不是“非空测试”,而是原始内容的重复性。

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

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