带有java中自定义对象的列表的深层副本

sag*_*uri 2 java android

我有一个包含自定义对象的List.我想创建该List的深层副本.这是自定义对象的类:

public class MyMemo {
    private List<Uri> imageUriList;
    private String commentText;

    public MyMemo(){
        imageUriList = new ArrayList<>();
    }

    public List<Uri> getImageUriList() {
        return imageUriList;
    }

    public void setImageUriList(List<Uri> imageUriList) {
        this.imageUriList = imageUriList;
    }

    public String getCommentText() {
        return commentText;
    }

    public void setCommentText(String commentText) {
        this.commentText = commentText;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我有以下情况:

List<MyMemo> parentList = new ArrayList<>();
List<MyMemo> copyList = new ArrayList<>(parentList);
parentList.get(currentMemoPosition).getImageUriList().removeAll(someOtherList.getImageUriList());
Log.e(TAG,"Total List: "+parentList.get(currentMemoPosition).getImageUriList().size()+" "+copyList.get(currentMemoPosition).getImageUriList().size());
Run Code Online (Sandbox Code Playgroud)

但是,如果我对parentListie中delete的项目或add新项目进行任何更改.copyList也受影响.如何确保copyList不引用相同的内存地址.

更新:

如建议使用clone().但问题是我的自定义对象中有一个列表.他怎么样clone()

Rav*_*avi 6

IMO,添加另一个 arg 构造函数,它将为您的对象进行深度克隆。

public class MyMemo {
    MyMemo(MyMemo memo)
    {
       this.commentText = memo.getCommentText();
       this.imageUriList = new ArrayList<>();
       for (Uri uri : memo. getImageUriList())
       {
           this.imageUriList.add(new Uri(uri));
       }
    }
    // rest of your code
}
Run Code Online (Sandbox Code Playgroud)

现在,迭代您的父 List 并克隆每个对象

List<MyMemo> parentList = new ArrayList<>();
List<MyMemo> copyList = new ArrayList<>();
for (MyMemo memo : parentList)
{
   // create new instance of MyMemo and add to the list
   copyList.add(new MyMemo(memo));
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*att 6

当您创建第一个列表时:

List<MyMemo> parentList = new ArrayList<>();
parentList.add(customObject1);
parentList.add(customObject2);
parentList.add(customObject3);
Run Code Online (Sandbox Code Playgroud)

parentList是自定义对象的引用列表.

将内容复制parentListcopyList:

List<MyMemo> copyList = new ArrayList<>(parentList);
Run Code Online (Sandbox Code Playgroud)

copyList现在包含相同对象的引用parentList.如果更改对象中parentList的对象也会更改,copyList因为它们是同一个对象.

要创建列表的深层副本,您需要一种方法来复制一个自定义对象.您可以实现复制构造函数或克隆方法:

class CustomObject {
    private String item1;
    private String item2;

    public CustomObject(String item1, String item2) {
        this.item1 = item1;
        this.item2 = item2;
    }

    // copy constructor
    public CustomObject(CustomObject other) {
        this.item1 = other.getItem1();
        this.item2 = other.getItem2();
    }

    // clone
    public CustomObject clone() {
        CustomObject newObj = new CustomObject(this.getItem1(), this.getItem2());
        return newObj;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样复制一个对象:

CustomObject newObj = new CustomObject(existingObj);
Run Code Online (Sandbox Code Playgroud)

或者像这样:

CustomObject newObj = existingObj.clone();
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用复制构造函数制作列表的深层副本:

List<CustomObject> copyList = new ArrayList<>();
for(CustomObject obj : parentList) {
    copyList.add(new CustomObject(obj));
}
Run Code Online (Sandbox Code Playgroud)

或克隆方法:

List<CustomObject> copyList = new ArrayList<>();
for(CustomObject obj : parentList) {
    copyList.add(obj.clone());
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用复制构造函数.您可以阅读Josh Block在Effective Java中关于克隆与复制构造函数的使用的好文章.