Java ArrayList copy

JavaArraylist

Java Problem Overview


I have an ArrayList l1 of size 10. I assign l1 to new list reference type l2. Will l1 and l2 point to same ArrayList object? Or is a copy of the ArrayList object assigned to l2?

When using the l2 reference, if I update the list object, it reflects the changes in the l1 reference type also.

For example:

List<Integer> l1 = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
    l1.add(i);
}

List l2 = l1;
l2.clear();

Is there no other way to assign a copy of a list object to a new reference variable, apart from creating 2 list objects, and doing copy on collections from old to new?

Java Solutions


Solution 1 - Java

Yes, assignment will just copy the value of l1 (which is a reference) to l2. They will both refer to the same object.

Creating a shallow copy is pretty easy though:

List<Integer> newList = new ArrayList<>(oldList);

(Just as one example.)

Solution 2 - Java

Solution 3 - Java

Yes l1 and l2 will point to the same reference, same object.

If you want to create a new ArrayList based on the other ArrayList you do this:

List<String> l1 = new ArrayList<String>();
l1.add("Hello");
l1.add("World");
List<String> l2 = new ArrayList<String>(l1); //A new arrayList.
l2.add("Everybody");

The result will be l1 will still have 2 elements and l2 will have 3 elements.

Solution 4 - Java

Another convenient way to copy the values from src ArrayList to dest Arraylist is as follows:

ArrayList<String> src = new ArrayList<String>();
src.add("test string1");
src.add("test string2");
ArrayList<String> dest= new ArrayList<String>();
dest.addAll(src);

This is actual copying of values and not just copying of reference.

Solution 5 - Java

There is a method addAll() which will serve the purpose of copying One ArrayList to another.

For example you have two Array Lists: sourceList and targetList, use below code.

targetList.addAll(sourceList);

Solution 6 - Java

Java doesn't pass objects, it passes references (pointers) to objects. So yes, l2 and l1 are two pointers to the same object.

You have to make an explicit copy if you need two different list with the same contents.

Solution 7 - Java

List.copyOf ➙ unmodifiable list

You asked:

>Is there no other way to assign a copy of a list

Java 9 brought the List.of methods for using literals to create an unmodifiable List of unknown concrete class.

LocalDate today = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ) ;
List< LocalDate > dates = List.of( 
    today.minusDays( 1 ) ,  // Yesterday
    today ,                 // Today
    today.plusDays( 1 )     // Tomorrow
);

Along with that we also got List.copyOf. This method too returns an unmodifiable List of unknown concrete class.

List< String > colors = new ArrayList<>( 4 ) ;          // Creates a modifiable `List`. 
colors.add ( "AliceBlue" ) ;
colors.add ( "PapayaWhip" ) ;
colors.add ( "Chartreuse" ) ;
colors.add ( "DarkSlateGray" ) ;
List< String > masterColors = List.copyOf( colors ) ;   // Creates an unmodifiable `List`.

By “unmodifiable” we mean the number of elements in the list, and the object referent held in each slot as an element, is fixed. You cannot add, drop, or replace elements. But the object referent held in each element may or may not be mutable.

colors.remove( 2 ) ;          // SUCCEEDS. 
masterColors.remove( 2 ) ;    // FAIL - ERROR.

See this code run live at IdeOne.com.

>dates.toString(): [2020-02-02, 2020-02-03, 2020-02-04] > >colors.toString(): [AliceBlue, PapayaWhip, DarkSlateGray] > >masterColors.toString(): [AliceBlue, PapayaWhip, Chartreuse, DarkSlateGray]

You asked about object references. As others said, if you create one list and assign it to two reference variables (pointers), you still have only one list. Both point to the same list. If you use either pointer to modify the list, both pointers will later see the changes, as there is only one list in memory.

So you need to make a copy of the list. If you want that copy to be unmodifiable, use the List.copyOf method as discussed in this Answer. In this approach, you end up with two separate lists, each with elements that hold a reference to the same content objects. For example, in our example above using String objects to represent colors, the color objects are floating around in memory somewhere. The two lists hold pointers to the same color objects. Here is a diagram.

enter image description here

The first list colors is modifiable. This means that some elements could be removed as seen in code above, where we removed the original 3rd element Chartreuse (index of 2 = ordinal 3). And elements can be added. And the elements can be changed to point to some other String such as OliveDrab or CornflowerBlue.

In contrast, the four elements of masterColors are fixed. No removing, no adding, and no substituting another color. That List implementation is unmodifiable.

Solution 8 - Java

Just for completion: All the answers above are going for a shallow copy - keeping the reference of the original objects. I you want a deep copy, your (reference-) class in the list have to implement a clone / copy method, which provides a deep copy of a single object. Then you can use:

newList.addAll(oldList.stream().map(s->s.clone()).collect(Collectors.toList()));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser309281View Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaSergii ZagriichukView Answer on Stackoverflow
Solution 3 - JavaAlfredo OsorioView Answer on Stackoverflow
Solution 4 - JavaHarshal WaghmareView Answer on Stackoverflow
Solution 5 - Javavaibhav agrawalView Answer on Stackoverflow
Solution 6 - JavaJB NizetView Answer on Stackoverflow
Solution 7 - JavaBasil BourqueView Answer on Stackoverflow
Solution 8 - JavaFlorian D.View Answer on Stackoverflow