Java - array, arrayList 에서 크기 가변의 내부 동작
참고 블로그 : https://beaniejoy.tistory.com/50
[Collection] ArrayList 특징 (add할 때의 내부동작)
Overview ArrayList의 add 과정 DEFAULT_CAPACITY를 넘겼을 때 ArrayList는 copy의 문제를 가지고 있다. ArrayList는 어떻게 사용해야될까 정리 📌 Overview ArrayList하면 코딩테스트나 실제 개발에 가장 많이 쓰이는 C
beaniejoy.tistory.com
단순히
배열 array, 리스트 List 에 대하여 학습을 하게 되면서 무슨 차이가 있길래? 우리는 이걸 공부해야할까를 생각하게 되었다.
그리고 추가적으로 arraylist에 add 를 하게 되었을때 어떤 방식으로 동작을 하게 될지에 대하여 궁금하게 되었다.
우리가 하는 배열 array는 처음 크기를 할당 하는 것이 중요하다.
왜냐하면 처음에 설정해둔 크기를 넘어가게 된다면, 복사를 해서 다시 배열을 만들어주는 비용이 들기 때문이다.
그렇다고 해서 처음부터 너무 큰 크기를 할당하는 것 또한 메모리를 낭비하는 결과를 초래할 수 있다.
그럼 Array vs ArrayList 는 뭔차이 일까?
단순히,
- Array
배열은 생성 시에 정해진 크기를 가지며, 이 크기는 나중에 변경할 수 없다.
원시 데이터 타입과 객체 모두의 원소를 저장할 수 있다.
정도가 있으며
- ArrayList
ArrayList는 동적으로 크기가 조절되며, 원소를 추가하거나 제거할 수 있다.
객체만을 저장할 수 있습니다. 원시 데이터 타입은 사용할 수 없다.
근데 위에서 말하는 동적이라는 말은 무슨 말일까?
무슨 마법같은 일을 하길래 저런 설명의 차이가 있을까?
사실 앞서 말한 것과 큰 차이가 없다. 말그대로 크기가 부족하면
다시 크기를 늘려 복사하고 만드는 과정을 ArrayList 객체 내에 구현된 method 에서 진행을 하게 된다.
이러한건 단순, Array 크기를 변경하게 되었을때 비슷한 성능을 내게 된다.
안에 있는 ArrayList 에 있는 내부코드를 보게 된다면 아래와 같이 기본적인 크기가 존재한다.
만약에 그 범위(크기)를 넘어가게 된다면, 알아서 크기를 늘려 복사를 하고 이사를 하는 과정을 하게된다.
private static final int DEFAULT_CAPACITY = 10;
아래의 코드는 ArrayList 내에 구현된 코드이며 크기가 증가하게 되었을 때 과정을 볼 수 있다.
add, grow 의 메서드를 보게 되었을때 크기의 가변 그리고 복사 과정을 볼 수 있다.
/**
* This helper method split out from add(E) to keep method
* bytecode size under 35 (the -XX:MaxInlineSize default value),
* which helps when add(E) is called in a C1-compiled loop.
*/
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
private Object[] grow() {
return grow(size + 1);
}
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
int newCapacity = ArraysSupport.newLength(oldCapacity,
minCapacity - oldCapacity, /* minimum growth */
oldCapacity >> 1 /* preferred growth */);
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
그럼 이러한 과정은 성능에 영향을 주게 된다.
따라서, LinkedList와 적절한 사용에 맞게 사용하면 더 좋은 성능을 내는 서비스를 운영할 수 있을 것이다.
끝
참고
https://zoozoozoo.tistory.com/596
Java - LinkedList (feat. vs ArrayList)
자바의 정석에 나온 내용 배열은 가장 기본적인 형태의 자료구조로 간단하며, 사용하기 쉽고 데이터를 읽어 오는데 걸리는 시간이 가장 빠르다는 장점을 가지고 있다. 하지만, 다음과 같은 단점
zoozoozoo.tistory.com