Java ArrayList copy
To create an exact duplicate of an ArrayList
in Java, you use the special Java syntax new ArrayList<>(originalList)
. A new ArrayList
object will be created, and it will contain the same elements as the original list.
If the list you're duplicating contains objects, be aware this is a shallow copy, implying the objects' references are duplicated, not the objects themselves. Essentially, the copied list points to the same instances of the objects.
If you wish to duplicate the content of the objects as well (aka create a deep copy), you will need to manually perform this operation, as the clone()
function of ArrayList
doesn't copy the objects' content.
Types of copying: Shallow vs Deep
Shallow copy: clone()
An alternate strategy to create a shallow copy involves using the clone()
function, which replicates the list's structure but not its objects.
Note: clone()
must be used with care. Since it is not type-safe, misuse could lead to a ClassCastException
at runtime.
Shallow copy: addAll()
The addAll()
function can append all the existing list's elements into a new list, effectively creating a simple shallow copy.
Shallow copy: Collections.copy()
For using Collections.copy()
, the destination list needs to be initialized with the correct size. This can be accomplished through the combination of Collections.copy()
and Collections.nCopies()
.
Deep copy: Manual or Cloneable
or Serialization
A deep copy requires additional steps, such as:
- A loop to manually copy individual elements.
- Using the individual elements' copy constructor or clone function if the elements implement the
Cloneable
interface. - Employing serialization techniques to deeply copy objects.
Mutable elements in an ArrayList
Mutable objects dilemma
Remember, a shallow copy that contains mutable objects will have the mutation effects ripple through both lists as they both refer to the same underlying objects. Therefore, it is crucial to understand your data types and whether they are mutable (like StringBuilder
) or immutable (like String
).
Deep copies to the rescue
A deep copy becomes necessary when working with mutable objects in an ArrayList. It ensures data integrity and prevents unintended changes that could lead to hard-to-debug issues.
Nested collections require nested copying
Nested ArrayLists, i.e., an ArrayList containing other collections (like ArrayList<ArrayList<String>>
), require both outer and inner list copies to be truly independent from the original.
Performance considerations for copying
Time is money...or performance
Both shallow and deep copies have time overheads. While a shallow copy has a time complexity of O(n), deep copying could be much more expensive depending on the complexity of the objects being copied.
The space-time trade-off
While a deep copy might spare you from quirky bugs due to inadvertent mutations, it occupies more memory as it replicates each element's data. A shallow copy, on the other hand, is more memory-friendly as it reuses the existing objects.
Was this article helpful?