Reputation: 923
Is it possible to the following? If yes, does it have any drawbacks or is there a better way to do this?
List<Integer> myList = new ArrayList<>();
myList.add(2);
myList.add(3);
// then add all the elements again
myList.add(myList);
Upvotes: 1
Views: 11061
Reputation: 5940
In case of basic data types (Boolean, Short, Integer, Long, Float, Double, String) they are immutable, meaning they will always be passed-by-value.
Integer X = 10;
Integer Y = X; // Y is 10, X is 10
Y = 20; // Y is 20, X is 10
X = 30; // Y is 20, X is 30
String A = "Test";
String B = A; // B is a copy of A; A & B are distinct
But the problem arise when you store objects, if you try to assign, you will end up copying the reference not the value.
Object C = new Object();
Object D = C; // C & D points at the same object
The best practice is to copy, otherwise if you work with Objects, you will end up with multiple references to the same objects.
class MyObj { private int val; public MyObj(int v){ val=v; } ..}
ArrayList<MyObj> list = new ArrayList<MyObj>();
list.add(new MyObj(2));
list.add(new MyObj(3));
list.addAll(list);
You might think the list has 4 objects now, except you'd be wrong, it has 2 references to 2 different objects each, a simple test will show how.
// prints: 2 3 2 3
for(MyObj m : list) System.out.print(" "+m.getVal());
// modify first item to 5
list.get(0).setVal(5);
// prints: 5 3 5 3
for(MyObj m : list) System.out.print(" "+m.getVal());
You can clone objects by either creating and initiating the objects manually.
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
MyObj t = new MyObj();
t.setVal(m.getVal());
list.add(t); // append
}
You can also have a copy-constructor and pass the object you want to clone onto.
class MyObj
{
..
public MyObj(MyObj o)
{
val = o.getVal();
}
}
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
list.add(new MyObj(m)); // append
}
Moreover your objects class can implement the interface Cloneable
and extend the clone
method.
class MyObj implements Cloneable
{
..
public Object clone() throws CloneNotSupportedException
{
return (MyObj)super.clone();
}
}
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
list.add(m.clone()); // append
}
Upvotes: 2
Reputation: 11621
The addAll
method of ArrayList
happens to work in Oracle's JDK (and OpenJDK). But it is not guaranteed to. The Javadoc for addAll
says:
The behavior of this operation is undefined if the specified collection is modified while the operation is in progress. (This implies that the behavior of this call is undefined if the specified collection is this list, and this list is nonempty.)
The question is actually not as pointless as some of the answers imply. Just "trying it" is not a sufficient test that something works correctly, as this case proves.
In fact, when thinking about whether list.addAll(list)
works, you need to ask yourself how it might be implemented. If it was simply iterating over list
and adding each element to the end of list
, you'd get a ConcurrentModificationException
(or else it would go into an infinite loop). That's why the Javadoc doesn't guarantee that such a call works. As it happens, Oracle's implementation copies the passed list to an array first, and then copies each element of the array to the end of the list. This means that calling addAll
for a list might not be as efficient as doing it yourself without creating an extra copy.
Upvotes: 4
Reputation: 140309
The main drawback with myList.add(myList);
is that it won't compile, because myList
isn't an Integer
.
You can, however, use:
myList.addAll(myList);
or
myList.addAll(new ArrayList<>(myList));
if you want to do it safely.
Upvotes: 1
Reputation: 2119
myList.addAll(myList);
=> Works.
myList.add(myList);
=> Won't compile, .add method requires an Integer (not int) as argument, you cannot call using another List.
Upvotes: 0