How to handle Exception in Java 8 Stream?

user3407267 picture user3407267 · Apr 13, 2017 · Viewed 19.5k times · Source

I have a method where I am traversing through a List and creating List. While doing so, I am calling a method(createResult) to will give a Result also throws CustomException which I am wrapping as ResultClassException. But I keep getting an error saying Unhandled Exception.

My Code :

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

Can Someone tell what I am doing wrong?

Answer

Olivier Gr&#233;goire picture Olivier Grégoire · Apr 13, 2017

You probably have too many responsibilities in your method. You should think about splitting it into a method that only maps and another one that gathers them.

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