grow the array only by 50%

The old implementation grew the array by 100% with each resize.
The new implementation reduces the memory usage for, especially
for large lists.
The new algorithm is overflow-concious.
This commit is contained in:
2017-09-26 19:59:50 +02:00
parent 4a07ed14b0
commit ab7d554d52

View File

@@ -13,6 +13,11 @@ public class IntList {
private static final int DEFAULT_CAPACITY = 10;
/**
* The maximum size of an array.
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private int[] data;
private int index = 0;
@@ -33,16 +38,16 @@ public class IntList {
* if initial capacity is negative
*/
public IntList(final int initialCapacity) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("initial capacity must not be negative");
if (initialCapacity < 0 || initialCapacity > MAX_ARRAY_SIZE) {
throw new IllegalArgumentException(
"initial capacity must not be negative and not larger than " + MAX_ARRAY_SIZE);
}
data = new int[initialCapacity];
}
/**
* Create a new {@link IntList} with a copy of the elements of
* {@code intList}.
* Create a new {@link IntList} with a copy of the elements of {@code intList}.
*
* @param intList
* the list to copy
@@ -172,9 +177,8 @@ public class IntList {
* @param length
* number of elements to remove
* @throws IndexOutOfBoundsException
* if {@code from} or {@code length} is negative, or if the
* range defined by {@code from} and {@code length} is out of
* bounds
* if {@code from} or {@code length} is negative, or if the range
* defined by {@code from} and {@code length} is out of bounds
*/
public void remove(final int from, final int length) {
@@ -221,9 +225,8 @@ public class IntList {
* number of elements
* @return the {@code length} elements starting at {@code from}
* @throws IndexOutOfBoundsException
* if {@code from} or {@code length} is negative, or if the
* range defined by {@code from} and {@code length} is out of
* bounds
* if {@code from} or {@code length} is negative, or if the range
* defined by {@code from} and {@code length} is out of bounds
*/
public int[] get(final int from, final int length) {
if (from < 0) {
@@ -260,12 +263,17 @@ public class IntList {
private void ensureCapacity(final int newElements) {
final int requiredCapacity = index + newElements;
if (requiredCapacity - 1 >= data.length) {
final int newCapacity = data.length * 2 > requiredCapacity ? data.length * 2 : requiredCapacity;
if (requiredCapacity < 0 || requiredCapacity > MAX_ARRAY_SIZE) {
// overflow, or too big
throw new OutOfMemoryError();
}
if (requiredCapacity > data.length) {
final int[] newData = new int[newCapacity];
System.arraycopy(data, 0, newData, 0, index);
data = newData;
int newCapacity = data.length + data.length / 2;
newCapacity = Math.max(requiredCapacity, newCapacity);
newCapacity = Math.min(MAX_ARRAY_SIZE, newCapacity);
data = Arrays.copyOf(data, newCapacity);
}
}