Java

[Java] ArrayList는 어떻게 동적으로 사이즈가 늘어나는가? add() flow(동작 방식)

Hyung1 2021. 1. 19. 21:22
728x90
반응형

ArrayList add() 동작방식

ArrayList는 내부에서 elementData 배열을 기반으로 구성되어 있다.

 

  • 생성자를 통해서 직접 element 배열의 capacity 설정이 가능하다. 기본 Capacity는 10이다.
  • ArrayList의 기본 생성자를 사용할 경우 elementData에 EMPTY_ELEMENTDATA (빈 Object 배열)을 할당한다.

 

add()의 내부구조

modCount++로 구조적으로 변경된 횟수를 카운트한다.

add(e, elementData, size);

 

위의 로직을 살펴보자.

 

  • 두 번째 파라미터는 오브젝트형 배열을 인자로 받고있고, 세 번째 파라미터는 int형 정수(size)를 받고있다.
  • s와 elementDate의 길이를 비교하여 배열의 사이즈를 조정해야 하는지 체크한다.
  • elementData = grow(); 이 부분이 배열의 크기를 동적으로 늘어나게 해준다.
  • size = s + 1; 클라이언트에서 보여질 arrayList의 사이즈를 늘린다. arrayList에서 size() 메서드를 사용하면 해당 변수를 반환한다

grow() 한 번 살펴볼까?

  • int minCapacity를 파라미터로 갖는 첫번 째 grow(int minCapacity)는 기존의 elemantData(클라이언트는 arrayList를 사용한다면 이 배열을 사용할 것이다)를 newCapacity 길이만큼 새로 늘어난 배열에 카피한다.
  • 파라미터가 없는 두번 째 grow()는 minCapacity(최소 용량)로 현재 사이즈에서 +1을 인자로 넣어준다.

grow(int minCapacity) 메서드의 newCapacity(minCapacity)도 살펴보자.

  • int newCapacity = oldCapacity + (oldCapacity >> 1); 기존 용량 + 기존 용량/2 (우측 쉬프트 연산)
  • ArrayList 기본 생성자를 사용할 경우 elementData에 EMPTY_ELEMENTDATA (빈 Object 배열)을 할당한다. 맨 처음 등장하는 if문은 새로운 용량이 기존의 용량의 +1 된 사이즈보다 작을 때, elementData이 DEFAULTCAPACITY_EMPTY_ELEMENTDATA (빈 Object 배열) 이라면 DEFAULT_CAPACITY (10) 으로 minCapacity 설정한다.
  • return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity  : hugeCapacity(minCapacity); 새로운 용량이 기존 용량의 +1 된 사이즈보다 크면 이 로직을 수행한다.
  • MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 이다. 즉, 2147483639

 

 

hugeCapacity(minCapacity)를 살펴보자.

 

최소용량이 MAX_ARRAY_SIZE를 넘어갈 경우 int의 최대치를 용량으로 부여하고, int의 범위를 넘어서면 outOfMemory 발생

정리

ArrayList 기본 생성자를 통해 사용 하고 있을 경우를 생각 해보면 element 배열 크기가 0 이기 때문에
첫 element 를 add 할때 배열의 resize 가 발생하고 배열 크기는 10 으로 설정 된다.
이후 ArrayList 에 10개의 데이터가 있고 데이터를 추가 하려고 하면 resize 가 발생하여 15 가 된다.
이렇게 임의의 capacity 를 설정하지 않는 일반적인 상황에서는 10 -> 15 -> 22 -> 33 -> 49 .... 로 배열 사이즈가 조정 된다.

 

element 배열의 capacity 가 조정 된 후 add() 하려는 element 가 배열에 추가 되고, ArrayList 의 size 가 1 증가 한다.

 

결론적으로  element를 add하려고 할 때, capacity가 elementData(배열)의 길이와 같아지면 일반적인 상황에서 기존의 용량 + 기존 용량/2 만큼 크기가 늘어난 배열에 기존 elementData를 copy한다.

 

이런 원리로 arrayList가 동적으로 크기가 늘어날 수 있는 것이다.

 

grow() 메서드로 용량을 늘린 뒤, 추가하려는 element를 할당하면 클라이언트 입장에서는 자동으로 사이즈를 늘려주면서 element가 추가된 것으로 보인다.

 

실제로는 가지고 있던 용량이 꽉 찼을 때, 용량이 기존의 1.5배를 늘린 새로운 배열에 기존 배열을 copy하는 것이다.

 

 

출처:

Carray On Progamming

FunDev Stidio

 

728x90
반응형