如何在Java 8 Stream中处理异常?

时间:2017-04-13 04:23:00

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

我有一个方法,我遍历List并创建List。在这样做时,我调用一个方法(createResult)来给一个Result也抛出CustomException,我将它包装为ResultClassException。但是我一直收到一条错误,说“未处理的例外”。

我的代码:

 private  List<Result> getResultList(List<String> results) throws ResultClassException {
    List<Result> resultList = new ArrayList<>();
        results.forEach(
                (resultName) -> {
                    if (!resultRepository.contains(resultName)) {
                       try {
                           final Result result = createResult(resultName);
                           resultList.add(result);
                       } catch (CustomException e) {
                           throw new ResultClassException("Error",e);
                       }

                    } else {
                        resultList.add(resultRepository.get(resultName));
                        log.info("Result {} already exists.", resultName);
                    }
                }
        );
        return  Collections.unmodifiableList(resultList);
    }

有人能说出我做错了吗?

4 个答案:

答案 0 :(得分:6)

您的方法可能有太多责任。您应该考虑将其拆分为仅映射的方法和收集它们的另一个方法。

private List<Result> getResultList(List<String> names) throws ResultClassException {
  try {
    return names.stream()
        .map(this::getOrCreateResult)
        .collect(collectingAndThen(toList(), Collections::unmodifiableList));
  } catch (RuntimeException e) {
    if (e.getCause() instanceof CustomException) {
      throw new ResultClassException("Error", e.getCause());
    }
    throw e;
    // Or use Guava's propagate
  }
}

private Result getOrCreateResult(String name) {
  if (!resultRepository.contains(name)) {
    try {
      return createResult(name);
    } catch (CustomException e) {
      throw new RuntimeException(e);
    }
  } else {
    log.info("Result {} already exists.", name);
    return resultRepository.get(name);
  }
}

答案 1 :(得分:1)

我不建议使用RuntimeException,因为这会让你陷入糟糕的编码习惯。尝试在getResultList(...)的调用方法中处理ResultClassException。

答案 2 :(得分:0)

You can't handle a checked exception from inside of Streams

一种解决方法是从RuntimeException抛出createResult或编写一个方法来包装createResult,它将捕获并处理已检查的异常。

答案 3 :(得分:0)

使用Java 8中的lambda表达式表示内部类。因此异常将被抛入您的匿名内部类。 尝试添加你添加你的地方                            抛出新的ResultClassException(“Error”,e);

                       Thread.getAllStackTraces()
                          .keySet()
                          .stream()
                          .map(Thread::getStackTrace)
                          .map(Arrays::asList)
                          .forEach(list -> System.out.println(list.stream()
                                                                  .map(i -> i.toString())
                                                                  .collect(Collectors.joining("\n\t"))));

并查看正在调用它的线程。您将看到您的异常超出了lambda所期望的范围。您将看到该流正在创建许多线程,并且您的异常不是您想要的线程的一部分。 你可以像这样包装你的方法: Java 8: How do I work with exception throwing methods in streams?