fix ArrayList performance issue

The ArrayList(Collection) constructor was allocating two arrays
instead of one due to an off-by-one error in ArrayList.grow.  This
commit fixes that and makes grow and shrink more robust.
This commit is contained in:
Joel Dice 2012-06-14 10:55:03 -06:00
parent c00f811a2f
commit 153b78f479
2 changed files with 28 additions and 12 deletions

View File

@ -29,14 +29,15 @@ public class ArrayList<T> extends AbstractList<T> implements java.io.Serializabl
addAll(source);
}
private void grow() {
if (array == null || size >= array.length) {
resize(array == null ? MinimumCapacity : array.length * 2);
private void grow(int newSize) {
if (array == null || newSize > array.length) {
resize(Math.max(newSize, array == null
? MinimumCapacity : array.length * 2));
}
}
private void shrink() {
if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) {
private void shrink(int newSize) {
if (array.length / 2 >= MinimumCapacity && newSize <= array.length / 3) {
resize(array.length / 2);
}
}
@ -74,16 +75,15 @@ public class ArrayList<T> extends AbstractList<T> implements java.io.Serializabl
}
public void add(int index, T element) {
size = Math.max(size+1, index+1);
grow();
int newSize = Math.max(size+1, index+1);
grow(newSize);
size = newSize;
System.arraycopy(array, index, array, index+1, size-index-1);
array[index] = element;
}
public boolean add(T element) {
++ size;
grow();
array[size - 1] = element;
add(size, element);
return true;
}
@ -137,8 +137,9 @@ public class ArrayList<T> extends AbstractList<T> implements java.io.Serializabl
System.arraycopy(array, index + 1, array, index, size - index);
}
-- size;
shrink();
int newSize = size - 1;
shrink(newSize);
size = newSize;
return v;
}

View File

@ -131,6 +131,20 @@ public class List {
expect(l.size() == 2);
}
private static void testGrow() {
ArrayList<Integer> foo = new ArrayList<Integer>(2);
foo.add(0);
foo.add(1);
foo.add(2); // first grow
foo.add(3);
foo.add(4); // second grow
foo.add(5);
for (int i = 0; i < foo.size(); i++) {
expect(i == foo.get(i));
}
}
public static void main(String args[]) {
ArrayList<Integer> l = new ArrayList<Integer>();
l.add(1); l.add(2); l.add(3); l.add(4); l.add(5);
@ -155,5 +169,6 @@ public class List {
testIterators2(new ArrayList());
testIterators2(new LinkedList());
testGrow();
}
}