Java中forEach循环遇SQLException时如何终止并继续外层循环
解决方案:终止嵌套forEach并保留外层循环
方案1:用普通for循环替代stream的forEach
这是最直接的实现方式,普通for循环原生支持break关键字,可以直接终止当前的切片循环,同时外层的文件迭代不受影响:
for (Iterator iterator = notLoadedFiles.iterator(); iterator.hasNext();) { SwapReport swapReport = (SwapReport) iterator.next(); Reader reader = Files.newBufferedReader(Paths.get(swapReport.getFilePath())); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT); List<CSVRecord> initList = csvParser.getRecords(); CSVRecord csvRecord = initList.stream().filter(record -> record.get(0).endsWith("@xxx.com")).findAny().orElse(null); if (csvRecord != null) { List<List<CSVRecord>> output = ListUtils.partition(initList, chunkSize); // 替换stream.forEach为增强for循环 for (List<CSVRecord> slice : output) { String inParams = slice.stream() .filter(record -> !record.get(0).endsWith("@xxx.com")) .map(record -> "'" + record.get(0) + "'") .collect(Collectors.joining(",")); try { setAccountData(inParams); } catch (SQLException e) { // 终止当前切片循环,外层for继续处理下一个文件 break; } } } }
方案2:用原子标志位控制stream迭代终止
如果不想放弃stream写法,可以用AtomicBoolean作为终止标志,在lambda中检查标志位来提前终止后续迭代:
import java.util.concurrent.atomic.AtomicBoolean; for (Iterator iterator = notLoadedFiles.iterator(); iterator.hasNext();) { SwapReport swapReport = (SwapReport) iterator.next(); Reader reader = Files.newBufferedReader(Paths.get(swapReport.getFilePath())); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT); List<CSVRecord> initList = csvParser.getRecords(); CSVRecord csvRecord = initList.stream().filter(record -> record.get(0).endsWith("@xxx.com")).findAny().orElse(null); if (csvRecord != null) { List<List<CSVRecord>> output = ListUtils.partition(initList, chunkSize); AtomicBoolean shouldStop = new AtomicBoolean(false); output.stream().forEach(slice -> { // 标志位为true时直接跳过当前迭代 if (shouldStop.get()) { return; } String inParams = slice.stream() .filter(record -> !record.get(0).endsWith("@xxx.com")) .map(record -> "'" + record.get(0) + "'") .collect(Collectors.joining(",")); try { setAccountData(inParams); } catch (SQLException e) { // 设置终止标志,后续切片不再处理 shouldStop.set(true); } }); } }
方案3:抛出非检查异常中断stream迭代
自定义一个RuntimeException,在捕获SQLException时抛出它,外层捕获后直接继续下一个文件的处理:
// 自定义非检查异常 class SliceProcessingException extends RuntimeException { public SliceProcessingException(Throwable cause) { super(cause); } } // 主逻辑代码 for (Iterator iterator = notLoadedFiles.iterator(); iterator.hasNext();) { SwapReport swapReport = (SwapReport) iterator.next(); Reader reader = Files.newBufferedReader(Paths.get(swapReport.getFilePath())); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT); List<CSVRecord> initList = csvParser.getRecords(); CSVRecord csvRecord = initList.stream().filter(record -> record.get(0).endsWith("@xxx.com")).findAny().orElse(null); if (csvRecord != null) { List<List<CSVRecord>> output = ListUtils.partition(initList, chunkSize); try { output.stream().forEach(slice -> { String inParams = slice.stream() .filter(record -> !record.get(0).endsWith("@xxx.com")) .map(record -> "'" + record.get(0) + "'") .collect(Collectors.joining(",")); try { setAccountData(inParams); } catch (SQLException e) { // 抛出异常终止整个stream迭代 throw new SliceProcessingException(e); } }); } catch (SliceProcessingException e) { // 捕获异常后不做额外处理,外层循环继续下一个文件 // 可在此处添加日志记录:e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者angus
相关产品推荐
相关产品推荐

