stream流浅拷贝

浅拷贝

在stream中未使用map等方式,此时是浅拷贝

java 复制代码
        List<EmapMachineDTO> distinctList = machineVOList.stream()
                .collect(Collectors.toMap(
                        dto -> buildDedupKey(dto.getDepartment(),
                                dto.getPhase(),
                                dto.getMachineId(),
                                dto.getModuleSec()),
                        Function.identity(),
                        (existing, replacement) -> existing
                ))
                .values()
                .stream()
                .collect(Collectors.toList());

后续对原来的 machineVOList 数据进行操作,是会影响到前面的 distinctList 这个数据的

java 复制代码
        for (EmapMachineDTO vo : machineVOList) {
            if (vo.getMachineId() != null) {
                .....  
                vo.setStatus(statusEnum.getCode());
                vo.setColor(statusEnum.getColor());
            }
        }

问题分析

你观察得很准确。原因在于 distinctList 中的对象和 machineVOList 中的对象是同一个引用,修改其中一个就会影响到另一个。

为什么会这样?

看这段去重逻辑:

java 复制代码
List<EmapMachineDTO> distinctList = machineVOList.stream()
        .collect(Collectors.toMap(
                dto -> buildDedupKey(...),
                Function.identity(),
                (existing, replacement) -> existing
        ))
        .values()
        .stream()
        .collect(Collectors.toList());

Function.identity() 直接使用的就是 machineVOList 里的对象本身,没有做任何拷贝。所以最终 distinctList 只是原列表中某些元素的引用集合。

后续的循环:

java 复制代码
for (EmapMachineDTO vo : machineVOList) {
    vo.setStatus(code);
    vo.setColor(color);
}

遍历的是同一个对象集合,当然就会把状态和颜色写到 distinctList 里包含的那些对象上(因为它们是同一个实例)。

这是问题吗?

从当前逻辑看,很可能正是你想要的效果 ------你最终输出的是 distinctListresp.setEmapMachineList(distinctList)),所以让去重后的数据也带上状态是正确的。但如果你的设计期望是两个列表互相独立,那就会出现副作用。

何避免(如果需要独立)?

方案1:拷贝后去重

在去重前就先做一份浅拷贝,例如:

java 复制代码
List<EmapMachineDTO> distinctList = machineVOList.stream()
        .map(dto -> {
            EmapMachineDTO copy = new EmapMachineDTO();
            BeanUtils.copyProperties(dto, copy); // 或者其他拷贝方式
            return copy;
        })
        .collect(Collectors.toMap(...))
        ...

这样修改 machineVOList 就不会影响 distinctList,反之亦然。

【×会影响】方案2:直接在 distinctList 上设置状态

如果你只需要 distinctList 带状态,那可以不修改 machineVOList,而是在得到 distinctList 后遍历它:

java 复制代码
for (EmapMachineDTO distinct : distinctList) {
    if (distinct.getMachineId() != null) {
        // 从 statusMap 中获取状态并设置到 distinct 上
    }
}

**【×会影响到原数据,我自己亲测,原数据就会带上distinctList遍历时设置的数据】**这样既避免了对原列表的副作用,逻辑也更清晰。

额外提醒

当前循环里可能出现一个 machineId 对应多条不同 key 的记录,它们会拿到同一个 status,这看起来是符合业务假设的。但要注意 statusMap 如果缺失某个 machineId,你用了 randomWeightedStatus() 作为默认值,这可能会导致同一个 machineId 在不同的调用里出现不同的随机状态(如果去重后有多条记录,它们的状态也可能不一致)。如果这是临时测试代码(// todo 暂时写死),上线前别忘记替换回真实数据。

相关推荐
long3161 小时前
Java 团队入门到精通学习资料
java·开发语言
vx-程序开发1 小时前
【java项目分享】springboot农产品销售平台14952
java·javascript·spring boot·python·eclipse·django·php
城管不管1 小时前
rabbitmq如何保证消息不丢失?解决方案又是什么?
开发语言·ai·面试·职场和发展·rabbitmq·php·agent
程序员良辰1 小时前
【TongWeb7】启动接近两分钟问题排查
java·开发语言·中间件
深色風信子1 小时前
Kotlin Bytedeco OpenCV 图像图像58 无缝克隆
开发语言·opencv·kotlin·bytedeco
朝阳391 小时前
react19【系列实用教程】实用组件封装
开发语言·前端·javascript
Wesleyblue2 小时前
python计算余弦相似性和汉明距离
python·余弦相似性·汉明距离·二进制编码·数值向量
我是苏苏2 小时前
C#基础:使用System.Speech.Synthesis离线播放/朗读文字内容
开发语言·c#
Patrick在香港2 小时前
Python依赖管理从踩坑到选型:pip/poetry/uv四种方案全面实测
开发语言·python·数据分析·scikit-learn·ai编程·pip·uv