web-dev-qa-db-fra.com

Comment gérer Exception dans Java 8 Stream?

J'ai une méthode où je traverse une liste et crée une liste. Ce faisant, j'appelle une méthode (createResult) afin que le résultat lève également une exception CustomException que je suis en train d'encapsuler en tant que ResultClassException. Mais je continue à recevoir une erreur en disant Exception non gérée.

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

Quelqu'un peut dire ce que je fais mal?

3
user3407267

Vous avez probablement trop de responsabilités dans votre méthode. Vous devriez penser à le diviser en une méthode qui ne fait que des cartes et une autre qui les rassemble.

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);
  }
}
6
Olivier Grégoire

Je ne suggérerais pas d'utiliser RuntimeException car cela vous mènerait à une mauvaise pratique de codage. Essayez de gérer ResultClassException dans la méthode d'appel de getResultList (...). 

1
msuper

Vous ne pouvez pas gérer une exception vérifiée depuis l'intérieur de Streams

Une solution de contournement peut consister à lancer une RuntimeException de createResult ou à écrire une méthode pour encapsuler createResult qui capturera et gérera l'exception vérifiée.

0
santosh-patil

Avec les expressions lambda dans Java 8, vous représentez des classes internes. Ainsi, l’exception sera levée dans votre classe interne anonyme. Essayez d’ajouter que là où vous ajoutez votre , Lancez une nouvelle ResultClassException ("Erreur", 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"))));

et voir le fil qui l'appelle. Vous verrez que votre exception est hors de la portée que vous attendiez avec les lambdas. Vous verrez que le flux crée de nombreux threads et que votre exception ne fait pas partie du thread que vous souhaitez. Vous pouvez envelopper votre méthode comme suit: Java 8 : Comment travailler avec des méthodes de lancement d'exception dans des flux?

0
strash