Reputation: 1086
I have 2 big lists that contain heavy objects and I need to join them into a single list. My first instinct was to create a new list and append the content of those 2 into it as follow:
List<Item> items = new ArrayList<>();
items.addAll(list1);
items.addAll(list2);
However, as this is an ArrayList in order to copy those 2 big lists I need to allocate new memory instead of using the existing once and copy the references.
My thought now was to use LinkedList and copy the end node of list1
into the head of list2
however as much as I can say from the documentation there is no such method.
Is there a better way to concatenate 2 lists without re-allocation of new memory? and if not, what is the best practice in such a case?
Upvotes: 0
Views: 99
Reputation: 718758
This is probably the most memory / GC efficient way to do it:
List<Item> items = new ArrayList<>(list1.size() + list2.size());
items.addAll(list1);
items.addAll(list2);
The trick is to provide an accurate capacity
when creating the list; see the javadoc. This saves any double copying to "grow" the target list (i.e. list
).
My thought now was to use
LinkedList
and copy the end node oflist1
into the head oflist2
however as much as I can say from the documentation there is no such method.
LinkedList
use more memory per list entry than ArrayList
. By a factor of 4 or more.
Besides, when you use addAll
from one LinkedList
to another, you are creating new list node objects.
I have 2 big lists that contain heavy objects ....
The weight (size) of the objects is not relevant. A List
contains references to the objects, not copies of the objects themselves.
Is there a better way to concatenate 2 lists without re-allocation of new memory?
There is no way to concatenate two java.util.List
instances without allocating more memory. The best you can do is minimize the allocation.
On the other hand ... if you were prepared to implement your own linked list data structure, you could join two lists together by "splicing" them. But you the List
API doesn't allow that kind of thing. (For a start, it mutilates the original lists.)
It is true that premature optimization is a bad thing. However, if you already have strong evidence that the lists involved will be large, then this is arguably not premature.
Upvotes: 3
Reputation: 2375
The lists hold references to objects, not actual objects themselves. Unless you want to create a new list which has to have a deep copy of all the objects.
list1.addAll(list2);
list2.clear();
// You could also reclaim memory using garbage collector.
list1.addAll(list2);
list2 = null;
System.gc(); // It's not guaranteed that Garbage collector will be invoked.
However, it mainly depends on you use case. Remember:-
Microoptimization is the root of all evil.
Upvotes: 0
Reputation: 3165
My thought now was to use LinkedList and copy the end node of list1 into the head of list2 however as much as I can say from the documentation there is no such method.
You can do the same using Array list as follows:
list1.addAll(list2);
And after adding list2, You can ask GC to reclaim the memory used by list2 as follows:
list2 = null;
Upvotes: 0