Copy List of objects by value in Java

I have a class that gets in its constructor a list of List<Object> objects. Each time a list can be made from elements of a different type . This is something in common, and I don’t know what their class type will be.

I want to keep my copy of a copy of this list before allowing the user to change its values. But since the copy is executed by reference, both lists (the original and the copy) change ...

How to copy a list by value?

Thanks Devora

+7
source share
7 answers

Your question is not clear.

  • If you need a small copy (that is, a copy of the list that will contain references to the objects in the original list, then the clone method will do the job, just like the constructor of copying to the List implementation class.

  • If you need a deep copy (i.e. a copy of a list containing copies of the source objects), then it is best to create a new list and populate it with clones of the original list items. However, there is a catch. By default, the clone method is not provided. Many common utility classes are cloned; user classes are not ... unless you have implemented it. If your list contains any non-clonable object, you will get runtime exceptions.

There are other options for deep copying clone , but like cloning, they do not work with all classes. Indeed, the essence of the problem is if your solution should be a common one.

+2
source

You need to create a new List , and then add a clone for each element of the original list.

 List<Object> copy = new ArrayList<Object>(inputList.size()); for (Object item : inputList) { copy.add(item.clone()); } 

Obviously, you need to check that the objects in your Cloneable list, otherwise they will not be copied correctly.

+1
source

Go through the transferred list and copy its contents to create a new list, which can then be used without changing the original list.

 private List<Object> clone; public Foo(List<Object> original) { this.clone = new ArrayList<Object>(list.size()); for(Object item: original) { clone.add(item.clone()); } } 
0
source
0
source

If your object does not contain any other references to another object, you can use Object.clone (), but if it is not, you need to make a deep clone.

0
source

In such situations, there are three general solutions:

(1) If you know that individual elements have clone () methods that work the way you intend, create a new array and fill it with clone () of each corresponding element. Generally, the “core” objects from the JDK, such as strings, numbers, etc., must be accurate. The disadvantage of clone () is that it is a little "empty gun": you do not know a priori exactly how deep the "clone" will be if the method was overridden for a particular class and which links could potentially be reused or not. It also has a special "strong" danger that subclasses of cloned objects that rely on logic in their constructor cannot work. But, as I say, simple JDK objects should be fine.

(2) Serialize an ObjectOutputStream list wrapped in a ByteArrayOutputStream. Then take the resulting byte array and wrap ByteArrayInputStream and ObjectInputStream around it and read a new, deep copy of the list from it.

(3) In an ideal world, create a new list by filling it with explicitly created “copies” of the objects in question. If this is not too cumbersome for the code, this is the ideal solution because you “know what is actually happening”: there will be no hidden surprises regarding objects that would be accidentally redirected and not re-created, for example, the clone () method didn't work as you expected.

Since you have a simple container object (a list of arrays) whose structure you can easily recreate, then (2) may be redundant. This can be convenient for re-creating more complex structures.

Re (1), you should be especially suspicious of cloning objects from third-party libraries , where objects have not been specifically designed with the clone () function in mind. The problem is that it is easy for people to subclass the JDK class (cloneable) or the token clone () method without thinking about it in detail - in my experience, clone () has some subtleties that many developers do not (for example, that the constructor does not call new object call), which can lead to unforeseen problems. Therefore, if you cannot see reliable source code to be sure that clone () will be safe, I would avoid this.

0
source

If you have:

 List<Object> objects 

You can copy this list:

 List<Object> newObjects = new ArrayList<Object>(objects); 

[Update: add a real implementation of ArrayList to prove that it copied new objects]

See the real implementation of ArrayList, it copies objects - does not contain a reference to the same object.

public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }

public Object[] toArray() { return Arrays.copyOf(elementData, size); }

-2
source

All Articles