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

Java修改数组时如何避免已存入Deque的历史数据同步变更

问题根因

你之前试的数组拷贝方法是浅拷贝,根本没切断引用关联:

  • Arrays.stream(cells).toArray(Cell[][]::new)只创建了新的外层二维数组对象,内层存的每一行Cell[]数组还是原数组的引用
  • 核心问题是数组里存的Cell是可变对象,浅拷贝不会复制Cell实例本身,快照和原数组指向同一个Cell对象,你改原对象的值,所有引用这个对象的地方都会同步变。

你之前用的List拷贝方案其实也是浅拷贝,只有当List存的是不可变对象(比如基础类型包装类、String)时才不会出问题,如果List存的是自定义可变对象,一样要做深拷贝才能避免联动修改。

解决方案

存快照的时候做完整深拷贝,保证队列里存的二维数组、内层行数组、每个Cell实例全是独立的新对象,和原数据完全没有引用关联。

循环实现(可读性最好,性能最优)

// 生成当前棋盘状态的深拷贝快照
Cell[][] snapshot = new Cell[cells.length][];
for (int i = 0; i < cells.length; i++) {
    snapshot[i] = new Cell[cells[i].length];
    for (int j = 0; j < cells[i].length; j++) {
        Cell source = cells[i][j];
        if (source != null) {
            // 创建全新Cell实例,复制属性值
            snapshot[i][j] = new Cell(source.getValue());
        }
    }
}
// 只把独立快照存入队列
cellsReserved.add(snapshot);

流式实现(代码更简洁)

Cell[][] snapshot = Arrays.stream(cells)
        .map(row -> Arrays.stream(row)
                .map(cell -> cell == null ? null : new Cell(cell.getValue()))
                .toArray(Cell[]::new))
        .toArray(Cell[][]::new);
cellsReserved.add(snapshot);

替换后运行结果就符合预期,会依次输出5、10。

注意:如果后续Cell类新增其他可变成员字段,拷贝逻辑里必须同步复制这些字段的内容,不然还是会有引用共享的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:24:25