본문

Vector와 ArrayList(JAVA)

반응형

# Vector와 ArrayList

이 둘은 List인터페이스를 구현하기 때문에 데이터의 저장순서가 유지되고 중복을 허용한다는 공통적인 특징을 갖는다.

ArrayList는 기존의 Vector를 개선한 것으로 Vector와 구현원리, 기능적인 측면에서 동일하다고 할 수 있다.
Vector는 기존에 작성된 소스와의 호환성을 위해서 계속 남겨 두고 있을 뿐이기 때문에 가능하면 Vector보다는 ArrayList를 사용하자.



# Vector와 ArrayList의 비교

- 공통점

List인터페이스를 구현한다

저장순서가 유지되고 중복을 허용한다

데이터와 저장 공간으로 배열을 사용한다


차이점

Vector는 멀티쓰레드에 대한 동기화가 되어있으나 ArrayList는 그렇지 않다.



Vector와 ArrayList는 Object배열을 이용해서 데이터를 순차적으로 저장한다.
예를 들면, 첫 번째로 저장한 객체는 Object배열의 0번째 위치에 저장되고 그 다음에 저장하는 객체는 1번째 위치에 저장된다.
이런 식으로 계속 배열에 순서대로 저장되며,
배열에 더 이상 저장할 공간이 없으면 보다 큰 새로운 배열을 생성해서 기존의 배열에 저장된 내용을 새로운 배열로 복사한 다음에 저장된다.


List subList(int fromIndex, int toIndex) : fromIndex부터 toIndex사이에 저장된 객체를 반환한다.

   실제로 반환되는 객체는 fromIndex부터 toIndex 전까지의 객체. 즉, listEx.subList(1,4)이면 1,2,3까지만 객체 반환


Source 01) ArrayListEx01.java

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package arrayList;
 
import java.util.ArrayList;
import java.util.Collections;
 
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));
 
        ArrayList list2 = new ArrayList(list1.subList(14));
        print(list1, list2);
 
        Collections.sort(list1); // list1과 list2를 정렬한다.
        Collections.sort(list2);
        print(list1, list2);
 
        System.out.println("list1.containsAll(list2) : " + list1.containsAll(list2));
 
        list2.add("B"); // 0 2 4 B
        list2.add("C"); // 0 2 4 B C
        list2.add(3"A"); // 0 2 4 A B C
        print(list1, list2);
 
        list2.set(3"AA");
        print(list1, list2);
 
        // list1에서 list2와 겹치는 부분만 남기고 나머지는 삭제한다.
        System.out.println("list1.retainAll(list2) : " + list1.retainAll(list2));
 
        print(list1, list2);
 
        // list2에서 list1에 포함된 객체들을 삭제한다.
  /*
  여기서는 list2의 각 요소를 접근하기 위해 get(int index)메서드와 for문을 사용하였는데,
  for문의 카운터를 0부터 증가시킨 것이 아니라, llist2.size()-1 부터 감소시키면서 거꾸로 반복시켰다.
 
  만일 카운터를 증가시켜가면서 삭제하면, 한 요소가 삭제될 때마다 빈 공간을 채우기 위해 
  나머지 요소들이 자리이동을 하기 때문에 올바른 결과를 얻을 수 없다. 그래서 카운터를 감소시키면서 삭제를 해야
  자리이동이 발생해도 영향을 받지 않고 작업이 가능하다.
  */
        for (int i = list2.size() - 1; i >= 0; i--) {
            if (list1.contains(list2.get(i)))
                list2.remove(i);
        }
 
        print(list1, list2);
    }
 
    static void print(ArrayList list1, ArrayList list2) {
        System.out.println("list1 : " + list1);
        System.out.println("list2 : " + list2);
        System.out.println();
    }
 
}
cs


Result)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
list1 : [542013]
list2 : [420]
 
list1 : [012345]          <-- Collections.sort(List l)를 이용해서 정렬하였다.
list2 : [024]
 
list1.containsAll(list2) : true    <--list1이 list2의 모든 요소를 포함하고  있는 경우에만 true를 얻는다.
list1 : [012345]
list2 : [024, A, B, C]        <-- add(int index, Object obj)를 이용해서 새로운 객체를 저장하였다.
 
list1 : [012345]
list2 : [024, AA, B, C]       <-- set(int index, Object obj)를 이용해서 저장된 객체를 변경하였다.
 
list1.retainAll(list2) : true        <-- retainAll의 작업결과로 list1에 변화가 있었으므로 true를 반환한다.
list1 : [024]                 <-- list2와의 공통요소 이외에는 모두 삭제되었다(변화가 있었다).
list2 : [024, AA, B, C]
 
list1 : [024]
list2 : [AA, B, C]
cs


위의 예제는 ArrayList의 기본적인 메서드를 이용해서 객체를 다루는 방법을 보여준다. 

ArrayList는 List 인터페이스를 구현했기 때문에 저장된 순서를 유지한다는 것을 알 수 있다.



- List 크기 설정 및 할당받기 : List list = new ArrayList(크기);


긴 문자열 데이터를 원하는 길이로 잘라서 ArrayList에 담은 다음 출력하는 예제이다. 

단순히 문자열을 특정크기로 잘라서 출력할 것이라면, charAt(int i)와 for문을 이용하면 되겠지만, 

ArrayList에 잘라서 담아놓음으로써 ArrayList의 기능을 이용해서 다양한 작업을 간단하게 처리할 수 있다.


Source 02) ArrayListEx02.java

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
package arrayList;
 
import java.util.ArrayList;
import java.util.List;
 
public class ArrayListEx02 {
 
    public static void main(String[] args) {
        final int LIMIT = 10// 자르고자 하는 글자의 개수를 지정한다.
        String source = "0123456789abcdefghijABCDEFGHIJ!@#$%^&*()zzz";
        int length = source.length();
 
            // 크기를 약간 크게 잡는다.
  List list = new ArrayList(length / LIMIT + 10); 
 
        for (int i = 0; i < length; i += LIMIT) {
            if (i + LIMIT < length// 아직 자를 길이가 남아있다면
                // source를 fromIndex부터 toIndex 길이만큼 분할하여 list에 add
                list.add(source.substring(i, i + LIMIT));
            else { // 아홉자리 이하의 길이만 남았을 경우
                list.add(source.substring(i));
            }
        }
 
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}
cs

Result)

1
2
3
4
5
0123456789
abcdefghij
ABCDEFGHIJ
!@#$%^&*()
zzz
cs

Vertor와 ArrayList 같이 배열을 이용한 자료구조는 데이터를 읽어오고 저장하는 데는 효율이 좋지만, 용량을 변경해야할 때는 새로운 배열을 생성한 후 기존의 배열로부터 새로 생성된 배열로 데이터를 복사해야하기 때문에 상당히 효율이 떨어진다는 단점을 갖고 있다.

때문에 처음에 인스턴스를 생성할 때, 저장할 데이터의 개수를 잘 고려하여 충분한 용량의 인스턴스를 생성하는 것이 좋다.




출처 및 참고자료 : JAVA의정석(남궁성 저)

반응형

공유

댓글