숫자 야구 게임 코드를 작성하는 도중에 갑자기 길이가 정해진 Array를 사용할 수 있는 어플리케이션에선 Array를 사용해도 괜찮지 않을까? 안될까? 라는 생각이 들었지만....
비교해보기 전에 우선 내가 알아야한다. Array와 ArrayList는 어떤 차이가 있을까?
간단히 말해서 Java에서의 Array는 고정된 길이를 가진 컨테이너 객체이다. 우리가 냉장고 싱싱 야채 칸에는 야채를 넣고 김치 칸에는 김치를 넣어 보관하듯 Array 또한 고정된 길이에 숫자 또는 문자 등의 데이터를 보관할 수 있다.
ArrayList는 Array와 다르게 길이를 조정할 수 있다. 때문에 새로운 데이터를 추가하면 새로운 데이터를 추가하려면 기존의 배열의 용량을 늘려야 하기 때문에 Array 보다는 살짝 느리다.
위 설명에서 보이는 가장 큰 차이점은 가변성이다. Array는 미리 고정된 길이를 가지고 생성되고, ArrayList는 딱히 지정이 없어도 Default 크기를 가지고 생성된다. ArrayList가 단순 속도면에서 살짝 밀리지만 어차피 티도 나지 않고 Array 보다 편리하다.
이 주제는 방금 생각나서 ArrayList의 add()에 들어가봤다.
// 우리가 흔히 사용하는 List<Integer>의 add()에 바로 접근하면 밑의 코드가 나온다.
// E는 List에 제네릭으로 정한 형식이고, e는 우리가 입력한 값이된다.
boolean add(E e);
바로 add()로 들어가면 배열 추가, 확장 메서드가 보이지 않아서 ArrayList로 들어갔다.
// ArrayList에 들어가서 add를 검색하고 가장 익숙한 메서드 하나를 가져왔다.
private void add(E e, Object[] elementData, int s) {
// size와 elementData의 길이가 같아지면 grow()를 해준다.
if (s == elementData.length)
elementData = grow();
// e 값을 입력하면 elementData[s]의 인덱스에 값을 넣는다.
// 값을 넣은 후에 사이즈에 1을 더해준다.
elementData[s] = e;
size = s + 1;
}
사이즈가 같아지면 grow()를 하고, 배열에 값을 할당한다.
// grow()에서 배열이 어떻게 늘어나는지 확인할 수 있다.
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)];
}
}
private Object[] grow() {
return grow(size + 1); // 최소 가용 범위를 1 더해준다.
}
ArrayList는 위 과정을 통해 배열에 값을 저장하고 배열의 크기를 확장한다.
다음 시간에..