【问题标题】:Throw an exception if a Stream has no result如果 Stream 没有结果,则抛出异常
【发布时间】:2017-01-12 18:06:24
【问题描述】:

我需要在 lambda 中抛出一个异常,但我不知道该怎么做。

到目前为止,这是我的代码:

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

我不知道该怎么做。有什么办法可以做到这一点,或者我只是通过应用过滤器来绕过它,这样过滤器就不会像这样转发空值 filter(product->product!=null)(即使是提示也会很有用:))

编辑实际的问题是我需要一个产品,如果它为空,那么它会抛出异常,否则它会通过,Java 8 Lambda function that throws exception? 中没有提到

我要重构的代码是

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);
}

我有另一个可能的解决方案

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;
    }

但是我想用函数式接口来解决它,如果我能用这种方法中的一行来实现就好了

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

如果我需要声明一个自定义方法来声明异常,那将不是问题

【问题讨论】:

  • 好吧,您是否需要实际的异常,这意味着您希望在有一个带有 null product 的产品时收到警报,或者您想忽略具有该值的产品?
  • 实际上filter(product->product!=null) 不允许空值通过,因此可能导致崩溃,因此是的,我希望得到通知
  • 如果可能,您应该在Optional 上使用ifPresent 而不是get,或者您可以使用orElseThrow

标签: java exception lambda java-8 java-stream


【解决方案1】:

下面的代码可以工作

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

我们也可以用过滤器链来写。

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

【讨论】:

    【解决方案2】:

    findFirst() 返回一个Optional,所以如果你想让你的代码在没有找到任何东西的情况下抛出异常,你应该使用orElseThrow 来抛出它。

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

    【讨论】:

    • @HelloWorld:顺便说一句,您的原始代码会跳过 null 元素,并且只有在没有匹配的(非null)元素时才会失败,而如果出现以下情况,此代码将立即失败它在比赛前遇到null 值。您必须决定是否应该在listOfProducts 中允许nulls。
    • @Holger 实际上,我删除了空检查过滤器,因为注释表明它旨在引发异常。但是非流代码也有这个空检查,但是流版本应该在产品ID过滤器之前有它,否则后者会抛出一个NPE。
    • 我在最终返回时添加了这个listOfProducts.stream() .filter(product -> product.getProductId().equalsIgnoreCase(productId)) .filter(product -> product != null).findFirst() .orElseThrow(() -> new IllegalArgumentException("product not found " + productId));希望它会阻止空值
    • @Holger,它会检查 null,我认为我不需要在这里抛出异常 :)
    • @HelloWorld:你必须应用null 过滤器之前 否则,尝试调用product.getProductId() 将已经导致NullPointerException 如果流遇到null。
    猜你喜欢
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2018-05-31
    • 2018-08-27
    • 1970-01-01
    相关资源
    最近更新 更多