일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 자이고트
- 물리 메모리
- 데코레이터 패턴
- 리사이클러뷰
- 내부 단편화
- apk 빌드 과정
- 디자인 패턴
- appcompatacitivity
- 리사이클러뷰풀
- http발전과정
- Android
- recyclerview
- 뷰홀더
- viewModelScope
- 상태관리
- appcompatactivity
- Kotlin
- NestedScrollView
- 플로이드워셜
- DiffUtil
- http 역사
- 절대 주소
- 프로세스
- flutter
- 안드로이드
- AAC
- 운영체제
- GetX
- AsyncListDiffer
- Dispatchers
- Today
- Total
hong's android
[Java] Arraylist의 길이 확장 방법 본문
Arraylist의 가변적이다. 어떻게 가변적이게 되었을까?
Arraylist의 내부는 배열로 선언된 변수(elementData), 리스트를 몇 개 저장하고 있는지에 대한 데이터가 있다. 필요할 때마다 해당 배열의 크기를 늘리는 작업을 하게 된다. 그렇기 때문에 우리는 가변적으로 Arraylist에 데이터를 추가할 수 있다.
*Jdk 버전에 따라 확장 방법의 차이가 있다. 또한 overflow에 대한 예외처리 여부에 따라 나뉠 수 있다.
Jdk 6
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
Jdk 6에선 ensureCapacity() 를 호출해서 배열의 확장 여부를 판단하고 확장한다.
만약 확장을 해야하는 경우 기존 배열의 크기 oldCapacity = (oldCapacity *3)/2 + 1 만큼 확장해준다. 따로 overflow에 대한 예외처리는 되어있지 않은 상태이다.
Jdk 7
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
if (minCapacity > 0)
ensureCapacityInternal(minCapacity);
}
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
ensureCapacityInternal()에서 확장 여부를 판단하고 grow() 메서드를 호출한다.
확장을 할 때 기존 Jdk6에서 사용한 oldCapacity = (oldCapacity *3)/2 + 1 곱하기와 나누기 연산자가 아닌 비트 연산자를 사용한다. 그 이유는 oldCapacity * 3 연산에서 overflow 위험이 있기 때문이다.
추가로 MAX_ARRAY_SIZE보다 새로 할당된 배열의 크기가 클 경우 overflow 여부를 판단하고 배열의 크기를 제할 할 수 있는 hugeCapacity()가 추가됐다.
minCapacity에 따라 newCapacity를 Integer.MAX_VALUE로 할당할지 여부를 판단한다. (Integer.MAX_VALUE로 배열을 할당해도 몇몇 경우에 JVM에서 overflow 오류가 나지 않기 때문이다. 하지만 그런 경우를 제외하곤 MAX_ARRAY_SIZE가 overflow에 안정적이 기 때문에 Arraylist에서 최댓값으로 사용하게 된다.)
Jdk 8
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != EMPTY_ELEMENTDATA)
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
ensureCapacityInternal 메서드에서 Arraylist 최초 생성 시 할당되는 EMPTY_ELEMENTDATA인 경우 DEFAULT_CAPACITY, minCapacity 둘 중 큰 값을 크기로 할당하는 코드가 추가되었다.
minCapacity가 크기가 10보다 작은경우 모두 Arraylist 내부 배열의 크기는 10으로 할당된다.
'Develop > Java' 카테고리의 다른 글
[Java] Map 인터페이스 (0) | 2022.12.31 |
---|---|
[Java] 자바와 Jvm에 대해서 (0) | 2022.12.26 |
[Java] DeadLock (0) | 2022.12.20 |
[Java] java.lang.String 클래스에 대해서 (0) | 2022.12.20 |
[Java] Abstract class VS Interface (0) | 2022.12.20 |