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

如何实现嵌套ArrayList的克隆?Java开发技术问询

克隆嵌套ArrayList<ArrayList<Ship>>的正确方式

嘿,我懂你的问题所在——你当前的代码只是把原列表里的子ArrayList的引用直接加到了seaClone里,这属于浅拷贝。也就是说,theSea里的子列表和seaClone里的子列表其实是同一个对象,修改其中一个的元素(比如新增、删除Ship),另一个也会跟着变;而且如果Ship对象本身的属性被修改,原列表和克隆列表里的Ship都会受到影响,因为它们指向的是同一个实例。

下面分两种常见需求给你解决方案:

需求1:仅克隆嵌套的ArrayList结构,Ship对象保持原引用

如果你只需要让seaClone的列表结构独立于原列表(比如可以单独增删子列表里的Ship元素,但Ship的属性修改会同步),可以给每个子列表创建新的ArrayList实例,复制原有的Ship引用:

ArrayList<ArrayList<Ship>> seaClone = new ArrayList<>();
for (ArrayList<Ship> row : theSea) {
    // 新建ArrayList并传入原row,快速复制所有Ship引用
    seaClone.add(new ArrayList<>(row));
}

这种方式简单高效,适合不需要完全隔离Ship对象的场景。

需求2:完全深拷贝,连Ship对象也独立克隆

如果你需要让seaClone里的所有Ship对象都和原列表完全独立(修改克隆后的Ship属性不会影响原列表),那需要Ship类本身支持克隆,常见的实现方式有两种:

方式A:给Ship实现拷贝构造函数

先给Ship类添加一个拷贝构造函数,用来复制原Ship的所有属性:

public class Ship {
    // 假设Ship的属性示例
    private int positionX;
    private int positionY;
    private String shipName;

    // 拷贝构造函数
    public Ship(Ship originalShip) {
        this.positionX = originalShip.positionX;
        this.positionY = originalShip.positionY;
        this.shipName = originalShip.shipName;
        // 如果有其他引用类型属性(比如武器、船员列表),也要手动复制其克隆对象
    }

    // 其他业务方法...
}

然后遍历嵌套列表,逐个克隆Ship并添加到新的子列表中:

ArrayList<ArrayList<Ship>> seaClone = new ArrayList<>();
for (ArrayList<Ship> row : theSea) {
    ArrayList<Ship> clonedRow = new ArrayList<>();
    for (Ship ship : row) {
        // 通过拷贝构造函数创建独立的Ship实例
        clonedRow.add(new Ship(ship));
    }
    seaClone.add(clonedRow);
}

方式B:让Ship实现Cloneable接口

另一种方式是让Ship实现Cloneable接口并重写clone方法:

public class Ship implements Cloneable {
    private int positionX;
    private int positionY;
    private String shipName;

    @Override
    protected Ship clone() throws CloneNotSupportedException {
        // 先调用父类的clone方法完成基本类型属性的复制
        Ship clonedShip = (Ship) super.clone();
        // 如果有引用类型属性,比如List<Crew>,需要在这里手动克隆:
        // clonedShip.setCrew(new ArrayList<>(this.getCrew()));
        return clonedShip;
    }

    // 其他业务方法...
}

然后在克隆列表时调用ship.clone():

ArrayList<ArrayList<Ship>> seaClone = new ArrayList<>();
try {
    for (ArrayList<Ship> row : theSea) {
        ArrayList<Ship> clonedRow = new ArrayList<>();
        for (Ship ship : row) {
            clonedRow.add(ship.clone());
        }
        seaClone.add(clonedRow);
    }
} catch (CloneNotSupportedException e) {
    // 处理克隆异常,比如转为运行时异常抛出
    e.printStackTrace();
    throw new RuntimeException("Failed to clone Ship instance", e);
}

注意事项

如果Ship类包含其他引用类型的属性(比如另一个自定义对象、集合),那么在克隆Ship时,也要对这些属性进行深拷贝,否则这些属性还是会和原Ship共享引用,达不到完全独立的效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:15:08