5 Different Ways To Copy List To Another In Java

When starting on working with Java more frequently because of a change of stuff to work on, I am starting to notice the little details that Java provides. One of them is about Java Collections. To be more precise, List, Set, and Map really caught my attention. Well, although Map is not really part of Collections, I found myself using them quite a lot of times.

You will definitely find yourself deal with them a lot when you are writing the program logic to handle values or data. However, unlike normal programmer who might just brush it off as they learn about them very early on, these things actually piqued my interest further causing me to wanting to actually think more about them. However, the one thing that I am particularly interested in is copying of List as List is probably one of the most commonly used Collections out there.

So, in this article, I will be talking about List, especially how to copy one List to another List. What is a List? A List is an ordered collection of objects in which duplicate values are allowed to be stored. It also preserves insertion order. There are multiple ways on how to copy a list to another list. In order to copy a list to another list, there are about 5 ways of doing it:

  1. The constructor way
  2. The List addAll()
  3. The Collections Class
  4. The Java 8 Stream
  5. The Java 10 List copyOf()

The ways are not limited to the mentioned 5 only as there might be some more new ways coming up in the future with newer Java version releases. However, they are what I know for now.

So let’s get started!


1. The Constructor Way

Use the List constructor that takes in a collection as its argument. Just pass it another List object to create a new copy out of it.

Syntax:

List<T> copy = new ArrayList<>([to_be_copied_list]);

In this case, we are using a simple ArrayList class which implements the List interface. If you follow the syntax, it will be something like this example:

List<Integer> list = Arrays.asList(1,2,3);
List<Integer> copy = new ArrayList<>(list);
System.out.println(copy.toString());
// Output
[1, 2, 3]

This one is really simple to use. However, sometimes one would pick another way to suit their coding style or because of any other reasons.


2. The List addAll()

This method uses the addAll() method from the List itself. Now I know it does not really copy but just appending all the elements from a list to another. However, you can use it in a way to append all the elements into an empty List.

This will then create the illusion that it “copies” from a list to another empty list.

Syntax:

[dest_list].addAll([source_list]);

Example:

List<Integer> list = Arrays.asList(1,2,3);
List<Integer> copy = new ArrayList<>();
copy.addAll(list);
System.out.println(copy.toString());
// Output
[1, 2, 3]

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

Again, this is another easy one to use but a bit tricky. I don’t really use this but it is still good to know.


3. The Collections Class

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

One of them is copy(). It takes in 2 lists as parameters. One is the destination list which is the list you want to copy to, the other one is the source list which is the list you want to copy from.

It will maintain the index of each copied element in the destination list such as the original. We will see the example later.

Syntax:

Collections.copy([dest_list], [source_list]);

Example:

List<Integer> source = Arrays.asList(1,2,3);
List<Integer> dest = Arrays.asList(4,5,6,7,8);
Collections.copy(dest, source);
System.out.println(dest.toString());
// Output
[1, 2, 3, 7, 8]

Notice how the first three are overwritten. The indexes from the original list are all preserved in the new one. Therefore, still be careful on how you use it especially if that’s not your desired output.


4. The Java 8 Stream

Using Java 8, there is another way that makes this convenient too. It is by using Stream.

It is really useful as it can create a chain of methods that can be applied to collections through the use of Collection.stream().

Syntax:

list.stream()[.method()].collect(Collectors.toList());

The easiest, simplest way to use this is as follow:

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

Basically, it just goes through the List named “list” and then collects the data into a List and then assigns it to the “copy” List .

Now, we don’t usually use Stream this way as it provides a lot better ways to utilize it. Like the use of skip() or filter().

Example:

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

In the above example, we are skipping the first element from the “list” list when we are copying over to the “copy” list.

Example:

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

Meanwhile, the above example only copies string value of length above 10 only. Just like what the method name is, it filters.

For the filter condition, it can be of any. Therefore, you can use your creativity on how to filter a list out when dealing with different lists of objects.

This way of copying is much more useful because as you copy, you can filter out the stuff that you don’t want to be in your new list. This is probably widely used these days as you can see how useful it can be. There are a lot more methods besides skip() and filter() that you can use. They can also greatly reduce the lines of your code.


5. The Java 10 List copyOf()

Using Java 10, there is another way of copying a list through the use of copyOf(). It allows us to create an immutable List containing the elements of the given Collection. However, this thing is immutable. So you have to pay attention to it.

Syntax:

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

Example:

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

This one is pretty straightforward as well, just as shown in the example and you would have guessed what the values are.

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


Bonus

There is one thing that needs to be paid attention to when working with these is the ConcurrentAccessException.

This happens when you are trying to modify a list while trying to copy it. Probably only happens a lot when threads are involved.

There are about 3 ways to get around this exception:

  1. Use another collection that is designed for concurrent access.
  2. Lock it appropriately before using it.
  3. Try to avoid copying the original collection.

The details of each won’t be discussed here, but it is still good to know about the general overview of the exception that one might face while dealing with this, in this case it is the copying issue.


Conclusion

In this article, we saw the different ways of copying a list which are pretty diverse. We also saw various syntaxes that can be used as well as the bonus exception section to let you know what you may potentially face. Hopefully now you can have a better picture on what to use under which circumstances for the better of your code or program.

Additionally, hopefully now you have a rough idea on the variations to copy a list. It is never harmful to learn or know more as you won’t know when you might actually use them for the better of your code. The more you know, the more choices you have. 😉

That’s all for today’s article. If you spotted something that I am missing in this article, feel free to share it in the comment section below. We would all love to learn together. Also, if you find this useful for others, feel free to share as well!

Thanks for reading~