Reputation:
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
}
Upvotes: 7
Views: 241
Reputation: 718768
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; i.e. less than 1 microsecond difference. It is probably trivial compared with the rest of what the application is doing.
Upvotes: 2
Reputation: 51892
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;
}
Upvotes: 2
Reputation:
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.
Upvotes: 2
Reputation: 31878
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());
Upvotes: 10