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