简体   繁体   中英

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. 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.? Also, I would like to if checking for null each time is expensive than adding to list and iterating through it?

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:

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.

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. 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.


Also, I would like to if checking for null each time is expensive than adding to list and iterating through it?

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; ie less than 1 microsecond difference. 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:

 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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