Copy a List to Another List in Java

1. Overview

In this quick tutorial, we’ll show different ways to copy a List to another List and a common error produced in the process.

For an introduction to the use of Collections, please refer to this article here.

2. Constructor

A simple way to copy a List is by using the constructor that takes a collection as its argument:

List<Plant> copy = new ArrayList<>(list);

Due to the fact that we’re copying reference here and not cloning the objects,  every amends made in one element will affect both lists.

For that reason, using the constructor is good to copy immutable objects:

List<Integer> copy = new ArrayList<>(list);

Integer is an immutable class, its value is set when the instance is created and can never change.

An Integer reference can thus be shared by multiple lists and threads and there’s no way anybody can change its value.

3. List ConcurrentAccessException

A common problem working with lists is the ConcurrentAccessException. This could mean that we’re modifying the list while we’re trying to copy it, most likely in another thread.

To fix this issue we have to either:

  • Use a designed for concurrent access collection
  • Lock the collection appropriately to iterate over it
  • Find a way to avoid needing to copy the original collection

Considering our last approach, it isn’t thread-safe. So that if we want to resolve our problem with the first option, we may want to use CopyOnWriteArrayList, in which all mutative operations are implemented by making a fresh copy of the underlying array.

In case we want to lock the Collection, it’s possible to use a lock primitive to serialize read/write access, such as ReentrantReadWriteLock.

4. AddAll

Another approach to copy elements is using the addAll method:

List<Integer> copy = new ArrayList<>();
copy.addAll(list);

It’s important to keep on mind whenever using this method that, as with the constructor, the contents of both lists will reference the same objects.

5. Collections.copy

The Collections class consists exclusively of static methods that operate on or return collections.

One of them is copy, which needs a source list and a destination list at least as long as the source.

It will maintain the index of each copied element in the destination list such as the original:

List<Integer> source = Arrays.asList(1,2,3);
List<Integer> dest = Arrays.asList(4,5,6);
Collections.copy(dest, source);

In the above example, all the previous elements in the dest list were overwritten because both lists have the same size.

In case that the destination list size is larger than the source:

List<Integer> source = Arrays.asList(1, 2, 3);
List<Integer> dest = Arrays.asList(5, 6, 7, 8, 9, 10);
Collections.copy(dest, source);

Just the three first items were overwritten while the rest of the elements in the list are conserved.

6. Using Java 8

This version of Java opens our possibilities by adding new tools. The one we will explore in the next examples is Stream:

List<String> copy = list.stream()
  .collect(Collectors.toList());

The main advantages of this way are the opportunity to use skip and filters. In the next example we’re going to skip the first element:

List<String> copy = list.stream()
  .skip(1)
  .collect(Collectors.toList());

It’s possible to filter by the length of the String too or by comparing an attribute of our objects:

List<String> copy = list.stream()
  .filter(s -> s.length() > 10)
  .collect(Collectors.toList());
List<Flower> flowers = list.stream()
  .filter(f -> f.getPetals() > 6)
  .collect(Collectors.toList());

It’s probable we want to work in a null-safe way:

List<Flower> flowers = Optional.ofNullable(list)
  .map(List::stream)
  .orElseGet(Stream::empty)
  .collect(Collectors.toList());

And skip an element using this way too:

List<Flower> flowers = Optional.ofNullable(list)
  .map(List::stream).orElseGet(Stream::empty)
  .skip(1)
  .collect(Collectors.toList());

7. Using Java 10

Finally, one of the last Java version allows us to create an immutable List containing the elements of the given Collection:

List<T> copy = List.copyOf(list);

The only conditions are that the given Collection mustn’t be null, and it mustn’t contain any null elements.

8. Conclusion

In this article, we’ve explored different ways to copy a List to another List with different Java versions and a common error produced in the process.As always, code samples can be found over on GitHub.

Related posts:

Database Migrations with Flyway
Java Program to Implement LinkedBlockingDeque API
Java Program to Check Whether Topological Sorting can be Performed in a Graph
Wiring in Spring: @Autowired, @Resource and @Inject
Introduction to Java Serialization
More Jackson Annotations
Java Program to Implement String Matching Using Vectors
The “final” Keyword in Java
Using JWT with Spring Security OAuth (legacy stack)
Java Program to Implement Shoelace Algorithm
Prevent Cross-Site Scripting (XSS) in a Spring Application
Spring Boot - Zuul Proxy Server and Routing
Guide to @JsonFormat in Jackson
Automatic Property Expansion with Spring Boot
Java Program to Implement Hash Tables Chaining with Binary Trees
Spring Cloud AWS – S3
TreeSet và sử dụng Comparable, Comparator trong java
HttpClient Connection Management
So sánh ArrayList và LinkedList trong Java
Using the Map.Entry Java Class
Java Program to Implement DelayQueue API
Java Program to Implement Gauss Seidel Method
Lập trình đa luồng với CompletableFuture trong Java 8
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
Spring Boot: Customize the Jackson ObjectMapper
How to Iterate Over a Stream With Indices
Các kiểu dữ liệu trong java
Biểu thức Lambda trong Java 8 – Lambda Expressions
Java – Get Random Item/Element From a List
Java Program to Construct an Expression Tree for an Prefix Expression
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
Java Program to Implement Doubly Linked List