You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Lambda嵌套循环中NoSuchElementException异常修复

迭代器抛出NoSuchElementException异常修复及代码优化

问题描述

执行代码中int uploadId = uploadLogIdIterator.next().getUploadLogId();语句时,抛出java.util.NoSuchElementException异常,需要修复该问题并优化整体代码逻辑。

原业务代码

public SomeEntity saveGeneratedPriceInstructions(List<SomeDTO> someDTOList, boolean force) {
    List<String> weekNames = PeriodsUtils.getWeekNames(someDTOList.get(0).getWeekName());
    String codeToReturn = someDTOList.get(0).getCode();
    Set<String> encounteredCode = new HashSet<>();
    List<Integer> oldPIList = new ArrayList<>();
    List<SomeEntity> uploadLogToSaveList = new ArrayList<>();
    
    someDTOList.stream().map(SomeDTO::getCode).forEach(code -> {
        if (encounteredCode.contains(code))
            return;
        else {
            encounteredCode.add(code);
        }
        SomeEntity oldPI = someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusNotLikeOrderByUploadLogIdDesc(
                code, weekNames.get(0), APPROVED_STATUS);

        // 移除该注释如果不需要支持无补位的周号格式(如w1_2020)
        if (oldPI == null && weekNames.size() == 2) {
            oldPI = someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusNotLikeOrderByUploadLogIdDesc(
                    code, weekNames.get(1), APPROVED_STATUS);
        }

        if (oldPI != null) {
            oldPIList.add(oldPI.getUploadLogId());
        }
        SomeEntity uploadLogToSave = new SomeEntity(code, weekNames.get(0));
        uploadLogToSaveList.add(uploadLogToSave);
    });
    
    someRepository.deleteAllByIdInBatch(oldPIList);

    List<SomeEntity> someEntityList = (List<SomeEntity>) someRepository.saveAllAndFlush(uploadLogToSaveList);
    System.out.println("size" + someEntityList.size());

    Iterator<SomeEntity> uploadLogIdIterator = someEntityList.iterator();
    someDTOList.stream().map(SomeDTO::getCode).forEach(code -> {
        int uploadId = uploadLogIdIterator.next().getUploadLogId();
        someDTOList.stream().filter(someDTO -> someDTO.getCode().equals(code)).forEach(product -> {
            // 激活所有未激活的产品
            if (!product.isActive()) {
                pricingProductService.activateProduct(Long.valueOf(product.getProductCode()));
            }
            product.setId(0);
            product.setUploadLogId(uploadId);
            Integer weekId = modelPiWeekService.saveModelPiWeekDtoRestful(product).getId();
            getModelPiWeekDeltaDTOStream(product).forEach(period -> modelPiWeekDeltaService.saveModelPiWeekDeltaDtoRestful(weekId, period));
        });
    });
    
    return someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusEqualsOrderByUploadLogIdDesc(
            codeToReturn, weekNames.get(0), "C");
}

异常堆栈信息

java.util.NoSuchElementException: null
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1000) ~[na:na]
    at com.arcelormittal.ninasteel.nina_ui.service.ModelPiWeekUploadLogService.lambda$saveGeneratedPriceInstructions$5(ModelPiWeekUploadLogService.java:150) ~[classes/:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na]
    at com.arcelormittal.ninasteel.nina_ui.service.ModelPiWeekUploadLogService.saveGeneratedPriceInstructions(ModelPiWeekUploadLogService.java:149) ~[classes/:na]
    at com.arcelormittal.ninasteel.nina_ui.service.ModelPiWeekUploadLogService$$FastClassBySpringCGLIB$$59a8179d.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.20.jar:5.3.20]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.20.jar:5.3.20]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar:5.3.20]

异常原因分析

核心问题是:

  • someEntityList的元素数量是去重后的code数量(通过encounteredCode HashSet去重)
  • 但后续遍历的是someDTOList.stream().map(SomeDTO::getCode),包含大量重复的code,遍历次数远大于someEntityList的元素数
  • 迭代器的next()调用次数超过了集合元素总量,导致抛出NoSuchElementException

修复及优化后的代码

核心修复点

用Map<String, Integer>存储code与对应uploadId的映射关系,替代迭代器,彻底避免迭代器耗尽问题。

完整优化代码

import org.springframework.util.CollectionUtils;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public SomeEntity saveGeneratedPriceInstructions(List<SomeDTO> someDTOList, boolean force) {
    // 空列表判断,避免NPE
    if (CollectionUtils.isEmpty(someDTOList)) {
        return null;
    }

    List<String> weekNames = PeriodsUtils.getWeekNames(someDTOList.get(0).getWeekName());
    String codeToReturn = someDTOList.get(0).getCode();
    List<Integer> oldPIList = new ArrayList<>();

    // 提取去重后的code集合,替代手动维护HashSet
    List<String> distinctCodes = someDTOList.stream()
            .map(SomeDTO::getCode)
            .distinct()
            .collect(Collectors.toList());

    // 批量处理旧数据并构建待保存的uploadLog
    List<SomeEntity> uploadLogToSaveList = distinctCodes.stream().map(code -> {
        // 查询旧数据,用Optional避免多层null判断
        SomeEntity oldPI = Optional.ofNullable(someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusNotLikeOrderByUploadLogIdDesc(
                        code, weekNames.get(0), APPROVED_STATUS))
                .orElseGet(() -> {
                    if (weekNames.size() == 2) {
                        return someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusNotLikeOrderByUploadLogIdDesc(
                                code, weekNames.get(1), APPROVED_STATUS);
                    }
                    return null;
                });

        if (oldPI != null) {
            oldPIList.add(oldPI.getUploadLogId());
        }
        return new SomeEntity(code, weekNames.get(0));
    }).collect(Collectors.toList());

    // 批量删除旧数据,空列表直接跳过
    if (!CollectionUtils.isEmpty(oldPIList)) {
        someRepository.deleteAllByIdInBatch(oldPIList);
    }

    // 保存新的uploadLog并构建code与uploadId的映射
    List<SomeEntity> someEntityList = someRepository.saveAllAndFlush(uploadLogToSaveList);
    Map<String, Integer> codeUploadIdMap = someEntityList.stream()
            .collect(Collectors.toMap(SomeEntity::getCsuCode, SomeEntity::getUploadLogId));

    // 处理每个DTO,避免嵌套stream提升可读性
    someDTOList.forEach(product -> {
        String code = product.getCode();
        Integer uploadId = codeUploadIdMap.get(code);
        if (uploadId == null) {
            // 提前抛出明确异常,便于排查问题
            throw new IllegalArgumentException("未找到对应code的上传日志: " + code);
        }

        // 激活未激活产品
        if (!product.isActive()) {
            pricingProductService.activateProduct(Long.valueOf(product.getProductCode()));
        }

        product.setId(0);
        product.setUploadLogId(uploadId);
        Integer weekId = modelPiWeekService.saveModelPiWeekDtoRestful(product).getId();
        
        // 批量处理Delta数据,减少数据库交互次数
        List<ModelPiWeekDeltaDTO> deltaList = getModelPiWeekDeltaDTOStream(product)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(deltaList)) {
            // 建议新增批量保存方法,替代循环单条保存
            modelPiWeekDeltaService.saveAllModelPiWeekDeltaDtoRestful(weekId, deltaList);
        }
    });

    // 查询返回结果
    return someRepository.findOneByCsuCodeEqualsAndWeekNumberEqualsAndApprovalStatusEqualsOrderByUploadLogIdDesc(
            codeToReturn, weekNames.get(0), "C");
}

优化说明

  1. 空值防护:添加someDTOList空判断,避免调用get(0)时抛出NPE
  2. 去重逻辑简化:用stream().distinct()替代手动维护HashSet,代码更简洁易读
  3. 映射关系替代迭代器:用Map<String, Integer>存储code和uploadId的对应关系,彻底解决迭代器耗尽问题
  4. null处理优化:用Optional封装Repository查询结果,减少多层if-null嵌套
  5. 性能优化:将Delta数据收集为List后批量保存(需service支持),减少数据库交互次数
  6. 可读性提升:将嵌套的stream遍历改为直接遍历someDTOList,降低代码复杂度
  7. 异常明确化:添加uploadId为空的判断,提前抛出带有明确信息的异常,便于问题排查

内容的提问来源于stack exchange,提问作者Ranjana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:50:48