Java 버전 별 ArrayList add 동작
Java 6
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Java 6 에서 ArrayList add이다. ensureCapacity에 현재 size +1을 전달하여 크기를 확인한다.
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
ensureCapacity에서 기존 list의 크기와 비교해서 크기가 늘어야 한다면 기존 크기에 *3 / 2 +1하여 새로운 사이즈를 만들고 크기를 정하여 배열을 복사해준다.
Java 7
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Java7에서의 add이다. ensureCapacityInternal로 크기를 확인해준다.
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
데이터가 초기 빈 값이라면 DEFAULT_CAPACITY인 10과 비교하여 큰 값을 capacity로 설정하여 ensuerExplicitCapacity에 넘겨준다.
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
이렇게 넘어온 minCapacity가 현재 list 길이보다 크면 grow 를 실행한다.
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
Java7에서는 Java 6과 다르게 비트 연산으로 새로운 capacity를 계산한다. 만약 계산된 capacity가 MAX_ARRAY_SIZE (Java 7에서는 Integer.MAX_VALUE - 8) 보다 크다면 hugeCapacity를 호출한다.
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
만약 이렇게 넘어온 capacity가 overflow 되어서 음수가 되었다면 에러를 발생시킨다. 그게 아니라면 최대 Integer.MAX_VALUE 크기를 반환한다.
Java 8
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Java 8에서의 add이다. Java 7 과 마찬가지로 ensuerCapacityInternal을 호출해준다.
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
ensuerCapacityInternal 이다. Java 7 과 달라진점은 Java 7 에서는 encusrCapacityInternal 에서 계산하던 작업을 별도로 calculateCapacity로 분리해서 작업한다. 또 기존 Java 7 에서의 EMPTY_ELEMANTDATA 가 아니라 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 로 바뀌었다. 이건 초기값 없이 ArrayList를 초기화하면 기본적으로 갖게되는 값이다. 이 경우 기본적인 초기 사이즈는 10을 갖게 된다.
Java 8에서는 Java 7과는 다르게 빈 elementData와 초기 elementData를 분리해서 관리하고있다.