Java/Java Study

[Collections Framework] ArrayList

모모토 2021. 5. 27. 01:04
반응형


● ArrayList



ArrayList는 컬렉션 프레임워크에서 가장 많이 사용되는 컬렉션 클래스이다. 인터페이스 List를 상속받으므로 그 특징 또한 그대로 물려받는다.

ArrayList는 Array와 비슷한 면이 많지만 같진않다. 왜냐하면, Array는 정적 배열이고 ArrayList는 대표적인 동적 배열이다. ArrayList는 정적배열과는 다르게 추가, 삭제등을 할 수 있다. 이번 포스팅에선 ArrayList가 데이터를 저장하고 삭제, 추가하는 과정을 코드를 통해 조금 더 상세히 알아볼 것이다.


1) 순차적 데이터 저장 및 추가

ArrayList는 순차적으로 데이터를 저장하고 그 저장한 순서가 유지된다.
데이터를 추가할때는 ArrayList의 메서드, boolean add (Object o) 객체를 사용한다.( ArrayList 마지막에 추가, 추가 성공 시 true 반환)

public class ArrayList {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList(10);
        list1.add(new Integer(5));
        list1.add(new Integer(4));
        list1.add(new Integer(2));
        list1.add(new Integer(0));
        list1.add(new Integer(1));
        list1.add(new Integer(3));
     
        System.out.println(list1);
        }
    }


실행결과

[5, 4, 2, 0, 1, 3]


만약 중간에 추가하고 싶다면, 메서드 boolean add ( index , Object o)를 사용한다.(원하는 위치(index)에 Object를 저장)

public class ArrayListEx01 {
    public static void main(String[] args) {
        ArrayList list1 = new ArrayList(10);
        list1.add(new Integer(5));
        list1.add(new Integer(4));
        list1.add(new Integer(2));
        list1.add(new Integer(0));
        list1.add(new Integer(1));
        list1.add(new Integer(3));
        list1.add(3,9); //Integer는 써도 안써도 그만

        System.out.println(list1);
        }
   	}


실행결과

[5, 4, 2, 9, 0, 1, 3]


3번 인덱스에 9가 추가된 것을 확인할 수 있다.


2) ArrayList 데이터의 삭제

데이터의 삭제는 remove(index) 를 사용한다. (해당 index에 저장된 데이터를 삭제)

public class ArrayList { 
public static void main(String[] args) { 
 ArrayList list1 = new ArrayList(10); 
	list1.add(new Integer(5)); 
	list1.add(new Integer(4)); 
	list1.add(new Integer(2)); 
	list1.add(new Integer(0)); 
    	list1.add(new Integer(1)); 
	list1.add(new Integer(3)); 

	for (int i = list1.size() - 1; i >= 0; i--) { 
		list1.remove(i); System.out.println(list1); 
	} 
 } 
}


실행결과

[5, 4, 2, 0, 1] 
[5, 4, 2, 0] 
[5, 4, 2] 
[5, 4] 
[5] 
[]


배열의 마지막 요소였던 3부터 순차적으로 전부 지운다.

갑자기 문득 궁금한 점이 생긴다. 넣을 땐 5부터 넣었는데 왜 삭제할 땐 마지막에 넣은 3부터(요소의 마지막부터) 지우는 것일까?

반대로 첫번째 요소, 5부터 지워보자

public class ArrayListEx01 { 
public static void main(String[] args) {
ArrayList list1 = new ArrayList(10);
	list1.add(new Integer(5));
	list1.add(new Integer(4));
	list1.add(new Integer(2));
	list1.add(new Integer(0));
	list1.add(new Integer(1));
	list1.add(new Integer(3));

	long start = System.currentTimeMillis();

	for (int i = 0; i <= list1.size() - 1; i++) {
		list1.remove(i); System.out.println(list1); 
	} 

	long end = System.currentTimeMillis(); 

	System.out.println(end-start);//소요시간 
	} 
}


실행결과

[4, 2, 0, 1, 3] 
[4, 0, 1, 3] 
[4, 0, 3]

뒷요소부터 지울땐 정상적으로 지워졌지만 처음부터 지우려하니 요소가 다 지워지지도 않았고 지워지는 순서도 엉망인 것을 볼 수 있다.

그 이유는 , 배열의 맨 앞이나 중간의 요소를 지울 때, 배열의 빈부분을 채워주어야 하는데 이 과정에서 배열의 복사가 일어난다. 배열을 복사하여 붙여 넣음으로써 삭제된 요소들을 앞으로 한 칸씩 당기기 때문이다.

처음에 5를 지우고 그다음에 4를 지워야 하는데 배열의 복사가 일어나 5의 빈자리를 메꾸어주었기 때문에 4가 있어야 할 1번 인덱스에 2가 오게 되면서 4는 지우지 못하고 2를 지워버리며 결과적으론 지우지 못하는 요소들이 남게 돼버린다.

ArrayList의 이러한 특성 때문에 맨 뒷부분부터 요소를 제거해나가면 이러한 과정(배열의 복사)이 필요가 없으므로 ArrayList는 마지막 요소부터 제거해주는 것이 효율적이다.

3) 메서드 remove()

remove메서드를 사용할 때 배열의 복사가 어떻게 일어나는지 코드를 보면서 이해를 해보자

Object[] data = null; 
//생성자에서 size를 받아서 저장 

@Override 
public Object remove(int index) { 
Object oldObj = null; 

if (index < 0 || index >= size) { 
throw new IndexOutOfBoundsException("범위를 벗어났습니다"); 
} 
oldObj = data[index]; 

if (index != size - 1) {//만약 삭제하는 요소가 마지막 요소가 아니라면 배열의 복사과정을 거쳐야함 
System.arraycopy(data,index+1,data,index,size-index-1);//배열의 복사 
} 

data[size - 1]=null; //마지막 index를 비워줌 
size--; 
return oldObj; 
}


위의 메서드를 이용하여 배열의 중간에 있는 요소를 지워보자

public class ArrayList { 
public static void main(String[] args) {
ArrayList list1 = new ArrayList(5); //용량을 5로 수정
	list1.add(new Integer(0)); 
	list1.add(new Integer(1)); 
	list1.add(new Integer(2)); 
	list1.add(new Integer(3)); 
	list1.add(new Integer(4)); 
	list1.remove(2); 
	
	System.out.println(list1); 
	} 
}

위의 코드는 ArrayList객체를 생성하면서 용량을 5로 선언하였다는 것을 참고하자.

실행결과

[0, 1, 3, 4]


2를 지우는 과정에서 배열의 복사가 일어났다. 이를 그림으로 표현해보자면 아래와 같다.

이렇듯, 배열의 복사 과정은 복잡하고 시간이 더 걸리므로 가능하면 배열의 복사가 일어나지 않게 하기 위하며 인덱스의 마지막(index = size-1)부터 지워나가면 아래 그림과 같은 복잡한 과정을 거치지 않고 온전하게 데이터의 삭제가 가능해진다.