Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collections.copy problem

I want that b1 and b2 to have their own sets of elements, then b1 and b2 should have its own elements in memory so that when b1/b2 is modified, others should not be affected.

buffer is an ArrayList containing many elements

List<Integer>  b1 = new ArrayList<Integer>(buffer.size()) ;
List<Integer>  b2 = new ArrayList<Integer>(buffer.size()) ) ;
Collections.copy(b1, buffer);
Collections.copy(b2, buffer);

I am getting this exception:

Exception in thread "main"
java.lang.IndexOutOfBoundsException: Source does not fit in dest
    at java.util.Collections.copy(Collections.java:531)
    at Trees.containsSumPrint(Trees.java:243)
    at Trees.main(Trees.java:125)
like image 468
javaCollect Avatar asked Dec 17 '22 14:12

javaCollect


2 Answers

The ArrayList(int) constructor gives a List that has size 0 it only ensures that n elements can be added before it needs to reallocate the underlying array.

A better way you can copy the lists is:

b1.addAll(buffer);
b2.addAll(buffer);

The semantics are the same as when you would have first added buffer.size() nulls to each array and called Collections.copy(b1,buffer);


If you want a deep copy (the elements also copied) you are going to have to handle each element separately

for(MyObject obj:buffer){
    b1.add(obj.clone());
    b2.add(obj.clone());
}
like image 103
ratchet freak Avatar answered Dec 29 '22 10:12

ratchet freak


The Collections.copy(...) javadoc says this:

"Copies all of the elements from one list into another. After the operation, the index of each copied element in the destination list will be identical to its index in the source list. The destination list must be at least as long as the source list. If it is longer, the remaining elements in the destination list are unaffected.".

The ArrayList(int) constructor creates an empty list whose capacity (not size!) is given by the argument.

Since b1 is initially empty, copying a non-empty list to it (using copy) will fail, since the precondition (in bold) does not hold true (in general).

Basically, Collections.copy(...) is the wrong method to use.

What you should really be doing is this:

List<Integer> b1 = new ArrayList<Integer>(buffer.size());
List<Integer> b2 = new ArrayList<Integer>(buffer.size());
b1.addAll(buffer);
b2.addAll(buffer);

I'm assuming that you don't really want to create new instances of the list elements. If you do, I should point out that creating new instances of Integer objects is waste of time since Integer (like the other wrapper classes and String) is an immutable class.

like image 36
Stephen C Avatar answered Dec 29 '22 11:12

Stephen C