To populate a list, you must do two things repeatedly:
- Instantiating a new object
- Add that new object to the list
Your for
loop is doing just that. There is no more efficient way.
The instantiations take time, needing to find a piece of free memory, allocating that memory, filling that memory, and returning the address of that memory.
Adding each object to the list takes a moment, but a very brief moment. Remember that an ArrayList
is backed by an array. So the memory for the slots of that list have already been allocated. When you are calling ArrayList::add
, you are simply writing the object reference (pointer, memory address) into that existing blank slot.
The only performance hit is if you are adding more elements than is the current size and available room within the backing array. The array must be enlarged, if contiguous memory is available, otherwise a new larger array created and elements copied over. You can eliminate that minor hit by setting the initial capacity of the ArrayList
to be the number of expected elements. You set the initial capacity by passing a number to the constructor. If you over-estimated the number of elements, call ArrayList::trimToSize
to free up the memory used by the still-empty slots.
On a different subject, do not subclass ArrayList
without a very good reason. Your efficiency concerns do not warrant this move. The ArrayList
class is meant to be used as-is.
int limit = 52_000 ;
ArrayList< MyClass > list = new ArrayList<>( limit );
for ( int i = 0 ; i < limit ; i++ ) {
MyClass myElement = new MyClass() ;
list.add( myElement ) ;
}
// If any slots may not have been used, drop them to free up memory.
list.trimToSize() ;
You could condense the two lines inside the loop into one line.
list.add( new MyClass() ) ;
But that condensing will not likely impact performance. The optimizing compiler such as HotSpot or OpenJ9 is likely to this anyways, so I would not bother with the condensing. I prefer short separated lines for easier tracing and logging.