Philipp Sander
Philipp Sander

Reputation: 10249

Why doesn't Collections.copy increase the size of the destination?

I'm using the following code:

List<Object> dest = new LinkedList<Object>();
Collections.copy(oldList, src);

When i execute the code, I get an exception:

java.lang.IndexOutOfBoundsException: Source does not fit in dest
    at java.util.Collections.copy(Collections.java:589)

I know how to fix that, but what i don't understand is:

When i add elements manually, the list would increase the capacity automaticly. Why can't Collections#copy do that?

Upvotes: 5

Views: 4454

Answers (6)

Rohit Jain
Rohit Jain

Reputation: 213311

Collections#copy() is a utility method, that is intended to work for any List. This method is intended to just re-use the existing array and not allocate any memory. So, this might be efficient, else you might anyway use the ArrayList(Collection) constructor, which would do the expansion job for you. The fact that the size constraint, and expansion is only related to ArrayList can also be a reason, not to add this behaviour to the method. That would just be extra code for the sake of just a particular List implementation. That is not how programming to interface works.

And since it is clearly mentioned in the docs, they would expect you to follow it.

Upvotes: 3

Puce
Puce

Reputation: 38142

The Javadoc explains the behavior. Please read the Javadoc:

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#copy%28java.util.List,%20java.util.List%29

Upvotes: 0

sanbhat
sanbhat

Reputation: 17622

If you see the implementation of Collection.copy method, it maintains the identical indices in source and destination Lists, after the copy operation.

To set an element at an index, set(int) method should be used. set(int) method expects that the index is present in the destination list (unlike add(Object) which expands the list if there is no capacity).

Imagine if this method had used add(Object) while copying and the dest list had already had some elements, then the new elements (from src) would have got added at the end of dest list, breaking the copy contract (which means same elements @ respective same indices)

Hence the method throws exception if the destination list is not as long as source list

Upvotes: 1

Smutje
Smutje

Reputation: 18163

You assume, a List size is mutable and Collections.copy() does not assume this to theoretically broaden the purpose of this class to all classes implementing the List interface instead of the mutable ones only.

Upvotes: -1

Marco13
Marco13

Reputation: 54659

As StinePike already said in https://stackoverflow.com/a/21986805 : That's how it is implemented. It is just a convenience method that you can use instead of a for-loop like

for (int i=0; i<src.size(); i++)
{
    dst.set(i, src.get(i));
}

Regarding your question about the automatic size increase: It sounds as if you are actually looking for something like Collection#addAll(Collection) - so in this case

dest.addAll(src);

Upvotes: 4

stinepike
stinepike

Reputation: 54692

Because this is how it is implemented. If you see the source code of this method you will see that

 if (srcSize > dest.size())
    throw new IndexOutOfBoundsException("Source does not fit in dest");

So if you want to implement autoincrement, Then write your own method.

Upvotes: 3

Related Questions