views:

6160

answers:

7

I have an ArrayList and I want to copy it exactly. I use util classes when possible ont the assumption that someone spent some time making it correct. So naturally I end up with the Collections class which contains a copy method.

ss I hav the following::

List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());

Collections.copy(b,a);

this fails because basically it thinks b isn't big enough to hold a. Yes I know b has size 0, but it should be big enough now shouldn't it? If I have to fill b first then Collections.copy becomes a completely useless function in my mind. So except for programming a copy function (which I'm going to do now) is there a proper way to do this?

+18  A: 

Just do:

List a = new ArrayList(); 
a.add("a"); 
a.add("b"); 
a.add("c"); 
List b = new ArrayList(a);

ArrayList has a constructor that will accept another Collection to copy the elements from

MrWiggles
as someone below comments, this is a shallow copy. Otherwise this would've been a fine answer. I suppose I should've specified that. Nevermind, I've moved on anyway.
Jasper Floor
+17  A: 

b has a capacity of 3, but a size of 0. The fact that ArrayList has some sort of buffer capacity is an implementation detail - it's not part of the List interface, so Collections.copy(List, List) doesn't use it. It would be ugly for it to special-case ArrayList.

As MrWiggles has indicated, using the ArrayList constructor which takes a collection is the way to in the example provided.

For more complicated scenarios (which may well include your real code), you may find the Google Java Collections library useful.

Jon Skeet
+1 for actually explaining what is going on
basszero
+6  A: 

the simplest way to copy a List is to pass it to the constructor of the new list:

List<String> b = new ArrayList<String>(a);

b will be a shallow copy of a

Looking at the source of Collections.copy(List,List) (I'd never seen it before) it seems to be for coping the elements index by index. using List.set(int,E) thus element 0 will over write element 0 in the target list etc etc. Not particularly clear from the javadocs I'd have to admit.

Gareth

Gareth Davis
why do you say 'shallow' copy? - me java noob
Martlark
By 'shallow copy' he means that after the copy the objects in b are the same objects as in a, not copies of them.
DJClayworth
The javadoc for Collections.copy() says "The destination list must be at least as long as the source list."
DJClayworth
I guess I just mean it took me a couple of looks to see what the function actually did and I can see how the questioner got a little confused with exactly what it does
Gareth Davis
+3  A: 

If you want to copy an ArrayList, copy it by using:

List b = new ArrayList();
b.add("aa");
b.add("bb");

List a = new ArrayList(b);
Martin C.
+3  A: 
List b = new ArrayList(a.size())

doesn't set the size. It sets the initial capacity (being how many elements it can fit in before it needs to resize). A simpler way of copying in this case is:

List b = new ArrayList(a);
cletus
A: 

Copy isn't useless if you imagine the use case to copy some values into an existing collection. I.e. you want to overwrite existing elements instead of inserting.

An example: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,3,4,4,4,] a.copy(b) = [1,2,3,4,5,3,3,3,3,4,4,4]

However I'd expect a copy method that would take additional parameters for the start index of the source and target collection, as well as a parameter for count.

See Java BUG 6350752

ordnungswidrig
+7  A: 

Calling

List b = new ArrayList(a);

works fine if you want a shallow copy, but if you want a complete copy (with separate copies of each element) then you can FOLLOW that statement with Collections.copy, ie:

List b = new ArrayList(a);
Collections.copy(b,a);

Then List b will have its own complete copy of the elements that don't reference List A's elements.

Stephen Katulka