reckless
reckless

Reputation: 923

Add elements of a list to the same list in java

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

Answers (4)

Khaled.K
Khaled.K

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

Klitos Kyriacou
Klitos Kyriacou

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

Andy Turner
Andy Turner

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);

Ideone demo

or

myList.addAll(new ArrayList<>(myList));

if you want to do it safely.

Upvotes: 1

Oussama Ben Ghorbel
Oussama Ben Ghorbel

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

Related Questions