0

My problem is that I want to copy an ArrayList with Objects in it.
Afterwards i want to change the Objects within my "copy List" without changing the Object within the source List.

I already tried:

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

The more specific problem is here:

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());
}

The Output I get is:

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

The Output I would want is:

Reg 1
5
15
100
Copy
2
2
2
Reg 1
5
15
100
Adrian
  • 363
  • 3
  • 12
  • 2
    [How to clone ArrayList and also clone its contents?](https://stackoverflow.com/questions/715650/how-to-clone-arraylist-and-also-clone-its-contents) – Abra Jan 29 '20 at 18:26

2 Answers2

2

ArrayList in java stores references to objects (not the object itself). When you make a copy, it copies references, and both lists contain refs to the same objects. So you have to make copy of each object yourself. You can do it using streams: copy = regions1.stream().map(e->new Exon(e)).collect(Collectors.toList()).. But you will have to implement copy constructor public Exon(Exon src) {/*copy fields from src to this*/}. And maybe you will have to do the same for nested objects, because they are stored as refs as well.

2

Simply you can create a copy constructor for Exon. then in foreach you must pass new Exon object.(with start=2)

A copy constructor: That's helpful when we want to copy a complex object that has several fields, or when we want to make a deep copy of an existing object.


1- Create copy constructor for Exon

public class Exon {

    private int start;

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

    //Main Constructor and Getters and Setters

   }

2- Create a copy from main list

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

I wrote your code as follows:

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());
        }
    }

Result :

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

This link might be useful for Copy Constructor