Dynamic Array Algorithm
The Dynamic Array Algorithm is an ingenious approach to managing the size of an array, such that it can grow or shrink depending on the number of elements being stored. In traditional static arrays, the size of the array is determined during the declaration and cannot be changed once it is created. However, dynamic arrays provide flexibility by allowing developers to add or remove elements from the array at runtime, without having to worry about the constraints of a fixed size. The key idea behind the algorithm is that it automatically reallocates memory for the array when required, and adjusts its capacity to ensure efficient resource utilization.
To achieve this dynamic behavior, the algorithm monitors the array's capacity and load factor (the ratio of the number of elements to the array's capacity). When the load factor exceeds a certain threshold, the algorithm reallocates the memory for the array, typically doubling its capacity. This reallocation involves creating a new, larger array, copying the elements from the old array to the new one, and then deallocating the memory of the old array. Conversely, when the load factor falls below a certain threshold, the algorithm may choose to shrink the array, freeing up resources. This is generally achieved by halving the capacity of the array when it reaches a low enough load factor. By dynamically adjusting the array size, the algorithm ensures that the array is both memory-efficient and able to accommodate an arbitrary number of elements.
package DataStructures.DynamicArray;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class DynamicArray<E> implements Iterable<E> {
private int capacity = 10;
private int size = 0;
private Object[] elements;
public DynamicArray(final int capacity) {
this.capacity = capacity;
this.elements = new Object[this.capacity];
}
public DynamicArray() {
this.elements = new Object[this.capacity];
}
public int newCapacity() {
this.capacity <<= 1;
return this.capacity;
}
public void add(final E element) {
if (this.size == this.elements.length)
this.elements = Arrays.copyOf(this.elements, newCapacity());
this.elements[this.size] = element;
size++;
}
public void put(final int index, E element) {
// Objects.checkIndex(index, this.size);
this.elements[index] = element;
}
public E get(final int index) {
return getElement(index);
}
public E remove(final int index) {
final E oldElement = getElement(index);
fastRemove(this.elements, index);
return oldElement;
}
public int size() {
return this.size;
}
public boolean isEmpty() {
return this.size == 0;
}
public Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
private void fastRemove(final Object[] elements, final int index) {
final int newSize = this.size - 1;
if (newSize > index)
System.arraycopy(elements, index + 1, elements, index, newSize - index);
elements[this.size = newSize] = null;
}
private E getElement(final int index) {
// Objects.checkIndex(index, this.size);
return (E) this.elements[index];
}
@Override
public String toString() {
return Arrays.toString(Arrays.stream(this.elements).filter(Objects::nonNull).toArray());
}
@Override
public Iterator iterator() {
return new DynamicArrayIterator();
}
private class DynamicArrayIterator implements Iterator<E> {
private int cursor;
@Override
public boolean hasNext() {
return this.cursor != size;
}
@Override
public E next() {
if (this.cursor > DynamicArray.this.size) throw new NoSuchElementException();
if (this.cursor > DynamicArray.this.elements.length) throw new ConcurrentModificationException();
final E element = DynamicArray.this.getElement(this.cursor);
this.cursor++;
return element;
}
@Override
public void remove() {
if (this.cursor < 0) throw new IllegalStateException();
DynamicArray.this.remove(this.cursor);
this.cursor--;
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (int i = 0; i < DynamicArray.this.size; i++) {
action.accept(DynamicArray.this.getElement(i));
}
}
}
public static void main(String[] args) {
DynamicArray<String> names = new DynamicArray<>();
names.add("Peubes");
names.add("Marley");
for (String name : names) {
System.out.println(name);
}
names.stream().forEach(System.out::println);
System.out.println(names);
System.out.println(names.size());
names.remove(0);
for (String name : names) {
System.out.println(name);
}
}
}