자바 벡터(Java Vector)
이번 포스팅의 주인공은 Vector입니다. 차근차근 자료구조 클래스들을 하나씩 뜯어보려고 하는데 Vector가 처음 시작하기에 좋을 것 같아서 Vector 클래스가 주인공이 되었습니다.
Initialize Vector
벡터는 기본적으로 다음과 같이 초기화를 할 수 있습니다.
// (1) // 기본적인 벡터 객체 생성 // 기본 크기는 10으로 설정된다. // 요소가 크기를 초과하는 경우 10개씩 커진다. Vector<Object> v = new Vector<Object>(); // Vector v = new Vector(); // 위와 동일 // (2) // 크기가 5인 벡터 생성 // 요소가 크기를 초과하는 경우 초기 크기 지정한 값만큼 커진다. // 이 예제 소스에선 5만큼 커진다. Vector<Object> v2 = new Vector<Object>(5); // (3) // 크기가 5이고 그 이상 요소 삽입시 크기를 10개씩 늘린다. Vector<Object> v3 = new Vector<Object>(5, 10);
그리고 벡터의 내부에는 데이터 저장 용도로 멤버 변수인 Object[]를 가지고 있습니다. 따라서 어떠한 형태의 데이터라도 Object를 상속 받고 있다면 같은 벡터 객체에 넣을 수 있습니다.
synchronized Method
벡터의 .add() 메소드는 다음처럼 정의 되어 있습니다.
public synchronized boolean add(E e)
이 코드가 뜻하는 것은 벡터는 요소 삽입시 동기화를 한다는 것입니다. 물론 .add() 메소드 외에도 많은 메소드들이 synchronized 키워드가 붙어 있습니다.
멀티 스레드 프로그램이라면 모를까, 만약 싱글 스레드 프로그램일 때 동기화를 수행하게 되면 성능 저하가 올겁니다. 만약 동기화가 필요한 자료구조가 필요하다면 HashTable등을 사용합시다. 따라서 비교적 성능이 낮은 벡터는 JDK 하위 버전의 호환성을 위해 있다고 봐야 합니다.
grow Size
만약, 벡터 클래스에서 정의된 크기를 초과하도록 요소를 삽입하면 어떻게 될까요?
그럴 때를 대비해서 벡터 클래스 내부에 다음과 같은 메소드가 준비 되어 있습니다.
private void grow(int minCapacity)
물론 private이기 때문에 직접 호출할 수는 없어요. :D (할 사람이 있나요? -_-)
위의 메소드를 이용해 .add() 메소드 수행시 벡터의 크기를 초과하는 경우 .grow() 메소드가 실행 됩니다. 이 메소드는 단순합니다. 벡터의 요소가 가득차게 되면 Arrays.copyOf() 메소드를 수행해서 자신이 가지고 있는 Object 배열의 크기를 늘립니다.
그리고, 일정 개수 이상(2^31-8) 크기를 초과하면 OutOfMemoryError 오류가 나게 됩니다.
Processing Image
간단하게 그림으로 알아봅시다... 대략적으로 아래처럼 됩니다.
# 크기가 6인 벡터의 동작 1. add(삽입) 1) 여유 공간 ▼ ╋━╋━╋━╋━╋━╋…╋ ╋━╋ ┃ A┃ B┃ C┃ D┃ E┃ ┃ ◀ ┃ F┃ ╋━╋━╋━╋━╋━╋…╋ ╋━╋ 2) ╋━╋━╋━╋━╋━╋━╋ ┃ A┃ B┃ C┃ D┃ E┃ F┃ ╋━╋━╋━╋━╋━╋━╋ 2. remove(삭제) 1) ▼ delete element ╋━╋━╋━╋━╋━╋━╋ ┃ A┃ B┃ C┃ D┃ -┃ F┃ ╋━╋━╋━╋━╋━╋━╋ 2) ╋━╋━╋━╋━╋━╋…╋ ┃ A┃ B┃ C┃ D┃ F┃ ┃ ╋━╋━╋━╋━╋━╋…╋ 3. grow(증가) 1) 크기보다 많이 요소를 삽입하면 ╋━╋━╋━╋━╋━╋━╋ ╋━╋ ┃ A┃ B┃ C┃ D┃ F┃ G┃ ◀ ┃ H┃ ╋━╋━╋━╋━╋━╋━╋ ╋━╋ 2) 기존의 크기만큼 벡터를 늘린다. ╋━╋…╋…╋…╋…╋…╋…╋ ╋━╋ …┃ G┃ ┃ ┃ ┃ ┃ ┃ ┃ ◀ ┃ H┃ ╋━╋…╋…╋…╋…╋…╋…╋ ╋━╋ 3) 기존 크기가 6이기 때문에 총 12의 크기를 가진 벡터가 되고 연산 진행 ╋━╋━╋…╋…╋…╋…╋…╋ …┃ G┃ H┃ ┃ ┃ ┃ ┃ ┃ ╋━╋━╋…╋…╋…╋…╋…╋
[TIP] Arrays.copyOf() 예제
int ary[] = {1,2,3}; int copyAry[] = Arrays.copyOf(ary, 5); System.out.println(Arrays.toString(copyAry)); // [1, 2, 3, 0, 0]
Summary
벡터 클래스는 JDK가 1.8버전까지 온 지금은 자주 사용 되지는 않습니다. 대체할 수 있는 자료구조 클래스들이 많아지기도 했구요. 제일 중요한건 항상 동기화임을 잊지 않으면 될 것 같습니다.