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); addAll(source);
} }
private void grow() { private void grow(int newSize) {
if (array == null || size >= array.length) { if (array == null || newSize > array.length) {
resize(array == null ? MinimumCapacity : array.length * 2); resize(Math.max(newSize, array == null
? MinimumCapacity : array.length * 2));
} }
} }
private void shrink() { private void shrink(int newSize) {
if (array.length / 2 >= MinimumCapacity && size <= array.length / 3) { if (array.length / 2 >= MinimumCapacity && newSize <= array.length / 3) {
resize(array.length / 2); 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) { public void add(int index, T element) {
size = Math.max(size+1, index+1); int newSize = Math.max(size+1, index+1);
grow(); grow(newSize);
size = newSize;
System.arraycopy(array, index, array, index+1, size-index-1); System.arraycopy(array, index, array, index+1, size-index-1);
array[index] = element; array[index] = element;
} }
public boolean add(T element) { public boolean add(T element) {
++ size; add(size, element);
grow();
array[size - 1] = element;
return true; 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); System.arraycopy(array, index + 1, array, index, size - index);
} }
-- size; int newSize = size - 1;
shrink(); shrink(newSize);
size = newSize;
return v; return v;
} }

View File

@ -131,6 +131,20 @@ public class List {
expect(l.size() == 2); 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[]) { public static void main(String args[]) {
ArrayList<Integer> l = new ArrayList<Integer>(); ArrayList<Integer> l = new ArrayList<Integer>();
l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); 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 ArrayList());
testIterators2(new LinkedList()); testIterators2(new LinkedList());
testGrow();
} }
} }