Explain Codes LogoExplain Codes Logo

How to copy Java Collections list

java
deep-copies
collections
performance
Alex KataevbyAlex Kataev·Feb 16, 2025
TLDR

Shallow copying a list? Use new ArrayList<>(originalList). If the golden destination is already awaiting duplicate guests, call on Collections.copy(dest, src). For those adventurous souls interested in deep copies of mutable objects, the map-stream-collect trinity is your best shot.

List<String> src = Arrays.asList("apple", "banana", "cherry"); // Beware: not a farm, just a supermarket List<String> shallow = new ArrayList<>(src); // Like a hotel guest list, but for fruits List<String> dest = new ArrayList<>(src.size()); Collections.fill(dest, null); // Making space for newcomers Collections.copy(dest, src); // Welcome party! // For your custom objects, we only clone on-demand: List<MyObject> deep = src.stream() .map(MyObject::new) // Because every MyObject is unique! .collect(Collectors.toList());

Get your buckets ready before copying

Copying collections isn't a casual affair. It's all about the type of copies - shallow, deep, and the objects' nature. Shallow copies are copying Chess Grandmaster references - great for immutable objects like String. For mutable objects, deep copies are the game - originals play at home, copies play away! Also, Collections.copy() comes in handy when you want to merge existing and new elements in a presized list.

Size matters - at least for destination lists

Remember to pump some iron, flex those list muscles with pre-sizing before Collections.copy():

Collections.copy(new ArrayList<>(originalList.size()), originalList);

Thrown in the gym is an IndexOutOfBoundsException - we don't want that, do we? Ensuring right-sized space for newcomers in destination list is a must.

Mutability - the game-changer for deep copies

Deep copy - the only way for lists with gym-freak mutable objects. If you've got custom objects flexing around, get Cloneable, implement your method:

List<MyObject> deep = originalList.stream() .map(myObj -> myObj.clone()) // Send in the clones! .collect(Collectors.toList());

Guava's Lists.copy to the rescue

For when you need the Avengers' support, Guava's Lists.copy() provides advanced copying options. It's like creating a **new ArrayList ** with the same team size and power:

List<String> guavaCopy = Lists.newArrayList(originalList);

Element updates: The game of musical chairs

For those fun nights with updating elements by index, the List.set(int, E) game is on. Perfect for musical chairs:

for (int i = 0; i < originalList.size(); i++) { copyList.set(i, new MyObject(originalList.get(i))); // And... pause the music! }

Performance: It's not always about being bulky

Doing the Hulk-show by preallocating capacity like new ArrayList<>(100) doesn't always give you the Thanos-like power. Be wary of "Thanos-perfect-balance" theories. Remember - Google is an Infinity Gauntlet.

Type-dependent deep copies

Deep copy methods wear their class-unique suits - one doesn't fit all scenarios.

Thrifty garbage collections with Collections.copy

Working with large lists? Use Collections.copy() for one-list-stand and **reusable arrays ** for reducing garbage collection load - it's all about being a thrifty Avenger!