I\'m not too concerned about time efficiency (the operation will be rare), but rather about memory efficiency: Can I grow the array without temporarily having all th
Heres a benchmark of time taken to add and remove elements from a collection/arraylist/vector
"Can I grow the array without temporarily having all the values twice?"
Even if you copy the arrays, you're only going to have all the values once. Unless you call clone() on your values, they're passed by reference into the new array.
If you already have your values in memory, the only additional memory expense when copying into a new array is allocating the new Object[] array, which doesn't take much memory at all, as it's just a list of pointers to value objects.
How about a linked list coupled with an array that holds only references.
The linked list can grow without having to allocate new memory, the array would ensure you have easy access. And every time the array becomes to small, you can simply trash the entire array and build it up again from the linked list.
Arrays are constant-size, so there is no way to grow them. You can only copy them, using System.arrayCopy to be efficient.
ArrayList does exactly what you need. It's optimized much better than any of us could do, unless you devote a considerable time to it. It uses internally System.arrayCopy.
Even more, if you have some huge phases where you need the list to grow/reduce, and others where it doesn't grow/reduce and you make thousands of read or write in it. Suppose also you have a huge performance need, that you prooved that ArrayList is too slow when read/writing. You could still use the ArrayList for one huge phase, and convert it to an array for the other. Note this would be effective only if your application phases are huge.
Obviously, the important bit here is not if you concatenate the arrays or copy them over; what's more important is your array growing strategy. It's not hard to see that a very good way to grow an array is always doubling its size when it becomes full. This way, you will turn the cost of adding an element to O(1) as the actual growing stage will happen only relatively rarely.
AFAIK the only way of growing or reducing an array is doing a System.arraycopy
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* @param index the index of the element to removed.
* @return the element that was removed from the list.
* @throws IndexOutOfBoundsException if index out of range <tt>(index
* < 0 || index >= length)</tt>.
*/
public static <T> T[] removeArrayIndex(T[] src, int index) {
Object[] tmp = src.clone();
int size = tmp.length;
if ((index < 0) && (index >= size)) {
throw new ArrayIndexOutOfBoundsException(index);
}
int numMoved = size - index - 1;
if (numMoved > 0) {
System.arraycopy(tmp, index + 1, tmp, index, numMoved);
}
tmp[--size] = null; // Let gc do its work
return (T[]) Arrays.copyOf(tmp, size - 1);
}
/**
* Inserts the element at the specified position in this list.
* Shifts any subsequent elements to the rigth (adds one to their indices).
*
* @param index the index of the element to inserted.
* @return the element that is inserted in the list.
* @throws IndexOutOfBoundsException if index out of range <tt>(index
* < 0 || index >= length)</tt>.
*/
public static <T> T[] insertArrayIndex(T[] src, Object newData, int index) {
Object[] tmp = null;
if (src == null) {
tmp = new Object[index+1];
} else {
tmp = new Object[src.length+1];
int size = tmp.length;
if ((index < 0) && (index >= size)) {
throw new ArrayIndexOutOfBoundsException(index);
}
System.arraycopy(src, 0, tmp, 0, index);
System.arraycopy(src, index, tmp, index+1, src.length-index);
}
tmp[index] = newData;
return (T[]) Arrays.copyOf(tmp, tmp.length);
}