如何处理 Java 8 Stream 中的异常?
How to handle Exception in Java 8 Stream?
我有一种遍历列表并创建列表的方法。在这样做的同时,我正在调用一个方法 (createResult) 来给出结果,同时抛出 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);
}
有人能告诉我哪里做错了吗?
You can't handle a checked exception from inside of Streams
一种解决方法是从 createResult
中抛出 RuntimeException
或编写一个方法来包装 createResult
,这将捕获并处理已检查的异常。
我不建议使用 RuntimeException,因为那会使您陷入糟糕的编码习惯。尝试在 getResultList(...) 的调用方法中处理 ResultClassException。
使用 Java 8 中的 lambda 表达式,您代表内部 classes。所以这个异常会在你的匿名内部class里面被抛出。
尝试在您要添加 throw new 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?
您的方法中可能有太多责任。你应该考虑把它分成一个只映射的方法和另一个收集它们的方法。
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);
}
}
如果部分处理的流是可以接受的(不是错误的),一种优雅处理的好方法:
List.of(1,2,3)
.stream().map( entry-> {
try {
return Optional.of(new Object());
} catch (Exception e) {
log.error("error [{}] while transforming entry [{}]", e.getMessage(), entry, e);
return Optional.empty();
}
}).filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
我有一种遍历列表并创建列表的方法。在这样做的同时,我正在调用一个方法 (createResult) 来给出结果,同时抛出 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);
}
有人能告诉我哪里做错了吗?
You can't handle a checked exception from inside of Streams
一种解决方法是从 createResult
中抛出 RuntimeException
或编写一个方法来包装 createResult
,这将捕获并处理已检查的异常。
我不建议使用 RuntimeException,因为那会使您陷入糟糕的编码习惯。尝试在 getResultList(...) 的调用方法中处理 ResultClassException。
使用 Java 8 中的 lambda 表达式,您代表内部 classes。所以这个异常会在你的匿名内部class里面被抛出。
尝试在您要添加 throw new 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?
您的方法中可能有太多责任。你应该考虑把它分成一个只映射的方法和另一个收集它们的方法。
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);
}
}
如果部分处理的流是可以接受的(不是错误的),一种优雅处理的好方法:
List.of(1,2,3)
.stream().map( entry-> {
try {
return Optional.of(new Object());
} catch (Exception e) {
log.error("error [{}] while transforming entry [{}]", e.getMessage(), entry, e);
return Optional.empty();
}
}).filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());