Some of the previous limitations can be overcome by suitably manipulating arrays, in such a way that the memory necessary to store the data of the application is allocated and deallocated dynamically during the program execution, depending on the needs.
The following example shows a class for dealing with a list of persons (objects of the class Person) that manages the size of the array dynamically.
public class ListOfPersonsArray {
private Person[] a;
private int n;
public ListOfPersonsArray() {
a = new Person[10];
n = 0;
}
// Add a person to the List of Persons in the last position
public void add (Person p) {
if (n == a.length) {
// The array is full!!!
// We have to create a new, bigger array and copy all elements
Person[] b = new Person[a.length*2];
for (int i=0; i<a.length; i++)
b[i] = a[i];
a = b;
}
// Now we are sure that n < a.length
a[n] = p;
n++;
}
// Remove the person in position k
public void remove (int k) {
if ((k >= 0) && (k < n)) {
// We have to move all elements that follow k
for (int i = k; i < n; i++)
a[i] = a[i+1];
n--;
}
// We reduce the dimension of the array if it is sufficiently empty
if ((a.length > 10) && (n < a.length/4)) {
Person[] b = new Person[a.length/2];
for (int i = 0; i < n; i++)
b[i] = a[i];
a = b;
}
}
}
Note that the dynamic management of the array is not done by dynamically changing its dimension (which is not possible), but by creating a new bigger or smaller array according to the application needs, and copying all values to the new array each time this becomes necessary.
The dimension of a new dynamically created array is doubled when new elements are necessary, and halved when the array is sufficiently empty. The choice of considering the array sufficiently empty when n < a.length/4 allows us to minimize the number of times it is necessary to create a new array, since at most half of the elements of the newly created array are used the moment the array is created.