如何在不指向 Java 源列表中的对象的情况下复制 ArrayList? [复制]

Posted

技术标签:

【中文标题】如何在不指向 Java 源列表中的对象的情况下复制 ArrayList? [复制]【英文标题】:How can i copy an ArrayList without pointing to the objects in the source List in Java? [duplicate] 【发布时间】:2020-05-15 07:24:53 【问题描述】:

我的问题是我想复制一个包含对象的 ArrayList。 之后我想更改“复制列表”中的对象而不更改源列表中的对象。

我已经试过了:

ArrayList<..> copy = new ArrayList<..>(sourceList); 
Collections.copy(dest, src);

更具体的问题在这里:

ArrayList<Exon> regions1 = new ArrayList<>();
regions1.add(r1);
regions1.add(r2);
regions1.add(r3);
System.out.println("Reg 1");
for (Exon e : regions1) 
    System.out.println(e.getStart());


ArrayList<Exon> copy = new ArrayList<>(regions1);
System.out.println("Copy");
for (Exon e : copy) 
    e.setStart(2);
    System.out.println(e.getStart());

System.out.println("Reg 1 - untouched");
for (Exon e : regions1) 
    System.out.println(e.getStart());

我得到的输出是:

Reg 1
5
15
100
Copy
2
2
2
Reg 1
2
2
2

我想要的输出是:

Reg 1
5
15
100
Copy
2
2
2
Reg 1
5
15
100

【问题讨论】:

How to clone ArrayList and also clone its contents? 【参考方案1】:

您只需为Exon 创建一个复制构造函数。然后在foreach 中你必须传递new Exon 对象。(with start=2)

复制构造函数:这在我们想要复制复杂的时候很有帮助 具有多个字段的对象,或者当我们想要制作深层副本时 现有对象。


1- 为Exon创建复制构造函数

public class Exon 

    private int start;

    //Copy constructor
    public Exon(Exon exon) 
        this.start = exon.getStart();
    

    //Main Constructor and Getters and Setters

   

2- 从主列表创建副本

 List<Exon> CopyList = mainList.stream().map(exon -> 
        Exon copyExon = new Exon();
        copyExon.setStart(2);
        return new Exon(copyExon);
    ).collect(Collectors.toList());

我写你的代码如下:

public static void main(String[] args) 

        //Initialize
        ArrayList<Exon> mainList = new ArrayList<>();
        Exon r1 = new Exon();
        r1.setStart(5);
        Exon r2 = new Exon();
        r2.setStart(10);
        Exon r3 = new Exon();
        r3.setStart(15);
        mainList.add(r1);
        mainList.add(r2);
        mainList.add(r3);

        //Print mainList
        System.out.println("Reg 1");
        for (Exon e : mainList) 
            System.out.println(e.getStart());
        

        //Copy the mainList (I changed your foreach)
        List<Exon> copyList = mainList.stream().map(exon -> 

            //Create New Exon
            Exon copyExon = new Exon(exon);
            copyExon.setStart(2);
            return copyExon ;

        ).collect(Collectors.toList());

        //Print copyList
        System.out.println("Copy");
        for (Exon e : copyList) 
            System.out.println(e.getStart());
        

        //Print mainList
        System.out.println("Reg 1 - untouched");
        for (Exon e : mainList) 
            System.out.println(e.getStart());
        
    

结果:

Reg 1
5
10
15
Copy
2
2
2
Reg 1 - untouched
5
10
15

This link 可能对 复制构造函数

有用

【讨论】:

帖子已编辑,(Copy the mainList 部分)。【参考方案2】:

Java 中的 ArrayList 存储对对象的引用(而不是对象本身)。当您制作副本时,它会复制引用,并且两个列表都包含对相同对象的引用。所以你必须自己复制每个对象。您可以使用流来做到这一点:copy = regions1.stream().map(e-&gt;new Exon(e)).collect(Collectors.toList()).。但是你必须实现复制构造函数public Exon(Exon src) /*copy fields from src to this*/。也许您必须对嵌套对象做同样的事情,因为它们也被存储为 refs。

【讨论】:

以上是关于如何在不指向 Java 源列表中的对象的情况下复制 ArrayList? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在不替换 ES6/Javascript 中的整个属性的情况下深度复制对象 [重复]

如何在不复制数组的情况下返回 Javascript 中的数组减去单个项目? [复制]

如何在不使用 Gradle 复制 jar 的情况下将一个模块的源包含在另一个模块中?

如何在不克隆的情况下复制 List<T>

如何在不使用 numpy 的情况下将 2D 列表展平为 1D? [复制]

如何在不复制对象的情况下向 Python 公开返回 C++ 对象的函数?