21

I need to throw an exception inside lambda and I'm not sure how to do it.

Here is my code so far:

listOfProducts
.stream()
.filter(product -> product.getProductId().equalsIgnoreCase(productId))
.filter(product -> product == null) //like if(product==null) throw exception
.findFirst()
.get()

I have no idea how to do that. Is there any way to do this or I just bypass it by applying filter so that filter will not forward null value like filter(product->product!=null) (even a hint will be useful :))

Edit The actuall question is I need a product and if it is null then it will throw exception otherwise it will pass, it's not mentioned in Java 8 Lambda function that throws exception?

The code I am trying to refactor is

for(Product product : listOfProducts) {
  if(product!=null && product.getProductId()!=null &&
      product.getProductId().equals(productId)){
    productById = product;
    break;
  }
}
if(productById == null){
  throw new IllegalArgumentException("No products found with the
    product id: "+ productId);
}

I have another possible solution as

public Product getProductById(String productId) {
        Product productById = listOfProducts.stream()
                .filter(product -> product.getProductId().equalsIgnoreCase(productId)).findFirst().get();

        if (productById == null)
            throw new IllegalArgumentException("product with id " + productId + " not found!");

        return productById;
    }

But I want to solve it using functional interface and it will be good if I can achieve this using one line in this method like

...getProductById()
return stream...get();

and If I need to declare a custom method to declare exception, it won't be an issue

Community
  • 1
  • 1
  • Well, do you need the actual exception, meaning you want to be alerted when there is a product with a null `product`, or do you want to ignore products with that value? – RealSkeptic Sep 05 '16 at 11:16
  • 2
    Possible duplicate of [Java 8 Lambda function that throws exception?](http://stackoverflow.com/questions/18198176/java-8-lambda-function-that-throws-exception) – ACV Sep 05 '16 at 11:17
  • actually `filter(product->product!=null)` will not allow null value to pass, and therefore can result in crash, and therefore yes I want to be notified –  Sep 05 '16 at 11:20
  • 2
    If possible you should use `ifPresent` rather than `get` on the `Optional` or you could use `orElseThrow` – greg-449 Sep 05 '16 at 11:36

2 Answers2

35

findFirst() returns an Optional so if you want to have your code throw an exception in case you didn't find anything, you should use orElseThrow to throw it.

listOfProducts
.stream()
.filter(product -> product.getProductId().equalsIgnoreCase(productId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No products found with the  product id: "+ productId));
Didier L
  • 18,905
  • 10
  • 61
  • 103
  • 2
    @HelloWorld: Just a side note, your original code skips `null` elements and will only fail, if there is no matching (non-`null`) element, whereas this code will immediately fail if it encounters a `null` value before the match. You have to make up your mind whether `null`s ought to be allowed in the `listOfProducts` or not. – Holger Sep 05 '16 at 11:53
  • 1
    @Holger Indeed, I removed the null check filter as the comment indicated that it was intended to throw an exception. However the non-stream code also had this null check, but then the stream version should have it before the product id filter, otherwise the latter will throw an NPE. – Didier L Sep 05 '16 at 11:56
  • I added this in final return `listOfProducts.stream() .filter(product -> product.getProductId().equalsIgnoreCase(productId)) .filter(product -> product != null).findFirst() .orElseThrow(() -> new IllegalArgumentException("product not found " + productId));` hope it will block null value –  Sep 05 '16 at 11:57
  • @Holger, it will check for null and I don't think I need to throw exception here :) –  Sep 05 '16 at 11:58
  • 1
    @HelloWorld: you have to apply the `null` filter *before* the other as otherwise, the attempt to invoke `product.getProductId()` will already cause a `NullPointerException` if the stream encounters `null`. – Holger Sep 05 '16 at 12:56
  • Didier L my question : if listOfProducts is empty then i want to throw an exception, saying that list of products is empty how can we do that. – Vijender Kumar Dec 11 '17 at 12:54
  • @VijenderKumar well just test if the list is empty and then throw your exception… If your need is more complex like that I suggest search for other similar question and then ask your own if necessary with the details of what you have tried. – Didier L Dec 11 '17 at 12:59
0

Below code would work

 listOfProducts
.stream()
.filter(product -> product != null &&   product.getProductId().equalsIgnoreCase(productId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No products found with the  product id: "+ product.getProductId()));

We can write the same with filter chaining as well.

listOfProducts
.stream()
.filter(product -> product != null)
.and(product.getProductId().equalsIgnoreCase(productId)))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No products found with the  product id: "+ productId));
Sanjay Bharwani
  • 3,317
  • 34
  • 31