如何使用 Java 中的 List 变量对对象进行深度复制?
How to make a deep copy of an object with a List variable in Java?
我在 Java 工作,我想制作 MoleculeDTO 对象的深拷贝。我也尝试制作一个复制构造函数,但它不起作用,它引用的是初始对象。
public class MoleculeDTO {
private int ID;
private String name;
private List<AtomDTO> atoms = new ArrayList<>();
private int nrAtoms =0;
public MoleculeDTO(String name, List<AtomDTO> atoms, int nrAtoms) {
this.name = name;
this.atoms = atoms;
this.nrAtoms = nrAtoms;
}
public MoleculeDTO(MoleculeDTO molecule) {
this(molecule.getName(), molecule.getAtoms(), molecule.getNrAtoms());
}
...getter, setter
}
这里是 class AtomDTO。
public class AtomDTO{
private int ID;
private String name;
private String symbol;
private int nrOfBonds;
private List<BondDTO> bonds = new ArrayList<>();
private int type;
private AnchorNode anchorNode;
public AtomDTO(String name, String symbol, int nrOfBonds, List<BondDTO> bonds, int type) {
this.name = name;
this.nrOfBonds = nrOfBonds;
this.bonds = bonds;
this.type = type;
}
public AtomDTO(AtomDTO copyAtom) {
this(copyAtom.getName(),copyAtom.getSymbol(), copyAtom.getNrOfBonds(), copyAtom.getBonds(), copyAtom.getType());
}
...getter, setter
}
这里是class BondDTO。
public class BondDTO {
private int ID;
private int otherAtomID;
private int otherAtomType;
private int bondType;
public BondDTO(int otherAtomID, int otherAtomType, int bondType) {
this.otherAtomID = otherAtomID;
this.otherAtomType = otherAtomType;
this.bondType = bondType;
}
public BondDTO(BondDTO copyBond) {
this(copyBond.getOtherAtomID(), copyBond.otherAtomType, copyBond.bondType);
}
...getter, setter
}
您的复制构造函数只是对每个字段进行浅表复制。这对字符串很好,因为它们是不可变的,对整数也很好,因为它们是原始的(这意味着它们缺乏身份并且是不可变的)。在那些情况下,浅拷贝和深拷贝之间没有重要区别。但它通常不适用于列表,因为列表可以是可变的,它们的元素也是如此。因此,您不仅需要指向同一个列表,还需要创建一个新列表并将原始列表的每个元素深度复制到新列表中。
使用此辅助方法对任何列表进行深层复制:
static <T> List<T> deepCopyList(List<T> list, UnaryOperator<T> deepCopyElement) {
return list.stream().map(deepCopyElement).collect(
Collectors.toCollection(ArrayList::new)
);
}
像这样:
public AtomDTO(AtomDTO that) {
this(that.getName(), that.getType(), deepCopyList(that.getBonds(), BondDTO::new));
}
我在 Java 工作,我想制作 MoleculeDTO 对象的深拷贝。我也尝试制作一个复制构造函数,但它不起作用,它引用的是初始对象。
public class MoleculeDTO {
private int ID;
private String name;
private List<AtomDTO> atoms = new ArrayList<>();
private int nrAtoms =0;
public MoleculeDTO(String name, List<AtomDTO> atoms, int nrAtoms) {
this.name = name;
this.atoms = atoms;
this.nrAtoms = nrAtoms;
}
public MoleculeDTO(MoleculeDTO molecule) {
this(molecule.getName(), molecule.getAtoms(), molecule.getNrAtoms());
}
...getter, setter
}
这里是 class AtomDTO。
public class AtomDTO{
private int ID;
private String name;
private String symbol;
private int nrOfBonds;
private List<BondDTO> bonds = new ArrayList<>();
private int type;
private AnchorNode anchorNode;
public AtomDTO(String name, String symbol, int nrOfBonds, List<BondDTO> bonds, int type) {
this.name = name;
this.nrOfBonds = nrOfBonds;
this.bonds = bonds;
this.type = type;
}
public AtomDTO(AtomDTO copyAtom) {
this(copyAtom.getName(),copyAtom.getSymbol(), copyAtom.getNrOfBonds(), copyAtom.getBonds(), copyAtom.getType());
}
...getter, setter
}
这里是class BondDTO。
public class BondDTO {
private int ID;
private int otherAtomID;
private int otherAtomType;
private int bondType;
public BondDTO(int otherAtomID, int otherAtomType, int bondType) {
this.otherAtomID = otherAtomID;
this.otherAtomType = otherAtomType;
this.bondType = bondType;
}
public BondDTO(BondDTO copyBond) {
this(copyBond.getOtherAtomID(), copyBond.otherAtomType, copyBond.bondType);
}
...getter, setter
}
您的复制构造函数只是对每个字段进行浅表复制。这对字符串很好,因为它们是不可变的,对整数也很好,因为它们是原始的(这意味着它们缺乏身份并且是不可变的)。在那些情况下,浅拷贝和深拷贝之间没有重要区别。但它通常不适用于列表,因为列表可以是可变的,它们的元素也是如此。因此,您不仅需要指向同一个列表,还需要创建一个新列表并将原始列表的每个元素深度复制到新列表中。
使用此辅助方法对任何列表进行深层复制:
static <T> List<T> deepCopyList(List<T> list, UnaryOperator<T> deepCopyElement) {
return list.stream().map(deepCopyElement).collect(
Collectors.toCollection(ArrayList::new)
);
}
像这样:
public AtomDTO(AtomDTO that) {
this(that.getName(), that.getType(), deepCopyList(that.getBonds(), BondDTO::new));
}