Java Vector 초기화 - Java Vector chogihwa

서론

알고리즘을 풀다보면, vector에서 row만 초기화하고 col은 push_back을 사용해야 하는 경우가 생긴다.

코드

아래와 같이 첫번째 인자만 할당해주거나 두번째 인자로 vector만 생성해주면 된다.

vector<vector<int>> graph(row);
vector<vector<int>> graph2(row, vector<int>());

아래와 같은 경우에서 사용할 수 있다.

#include <bits/stdc++.h>
using namespace std;

int main(){
    int numCourses = 2;
    vector<vector<int>> prerequisites = {{1,0},{0,1}};
    vector<vector<int>> graph(numCourses);
    for(auto i : prerequisites){
        graph[i[0]].push_back(i[1]);
    }

}

물론 2차원 vector의 row, col 을 모두 할당할 수도 있다. 아래와같이 하면된다.

vector<vector<int>> graph(row, vector<int>(col));

이번 포스팅의 주인공은 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버전까지 온 지금은 자주 사용 되지는 않습니다. 대체할 수 있는 자료구조 클래스들이 많아지기도 했구요. 제일 중요한건 항상 동기화임을 잊지 않으면 될 것 같습니다.


[개발 환경 설정]

개발 툴 : Eclipse

개발 언어 : Java

Java Vector 초기화 - Java Vector chogihwa

[소스 코드]

package ex6;

import java.util.Vector;

public class MainActivity {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("[Program Start]");
		System.out.println("");
				
		/**
		 * [Vector 객체 배열 선언 및 데이터 삽입, 포함 확인, 수정, 삭제 실시 - add , contains , set , remove]
		 * 1. Vector는 ArrayList와 동일한 내부구조를 가지고 있습니다
		 * 2. Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없습니다
		 * 3. Vector는 하나의 스레드가 실행을 완료해야만 다른 스레드들이 실행할 수 있습니다
		 * 4. Vector는 멀티 스레드 환경에서 안전하게 객체를 추가하고 삭제할 수 있습니다
		 * 5. Vector는 스레드가 1개일때도 동기화를 하기 때문에 ArrayList보다 성능이 떨어집니다
		 * */
		
		// 벡터 객체 생성 실시
		Vector vector = new Vector();// 제네릭 타입 미설정 Object로 생성됨
		
		// add 사용해 데이터 삽입 실시
		vector.add("투케이");
		vector.add("twok");
		System.out.println("add : " + vector.toString());
		System.out.println("size : " + vector.size());
		System.out.println("");
		
		// 특정 데이터 포함 여부 확인 실시		
		System.out.println("[투케이] contains : " + vector.contains("투케이"));
		System.out.println("[케이투] contains : " + vector.contains("케이투"));
		System.out.println("");
		
		// 특정 데이터 index 인덱스 번지 확인 실시
		System.out.println("[투케이] indexOf : " + vector.indexOf("투케이"));
		System.out.println("[케이투] indexOf : " + vector.indexOf("케이투"));
		System.out.println("");
		
		// 특정 번지 데이터 수정 실시
		vector.set(0, "투케이2K");
		System.out.println("[투케이 >> 투케이2K] set : " + vector.toString());		
		System.out.println("");
		
		// 특정 번지 데이터 삭제 실시
		vector.remove(1);
		System.out.println("[twok] remove : " + vector.toString());		
		System.out.println("");
		
		// 전체 배열 데이터 초기화 실시
		vector.clear();
		System.out.println("clear : " + vector.toString());		
		System.out.println("");

	}// 메인 종료

}// 클래스 종료

[결과 출력]

Java Vector 초기화 - Java Vector chogihwa

[요약 설명]

/**

* [Vector 객체 배열 선언 및 데이터 삽입, 포함 확인, 수정, 삭제 실시 - add , contains , set , remove]

* 1. Vector는 ArrayList와 동일한 내부구조를 가지고 있습니다

* 2. Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없습니다

* 3. Vector는 하나의 스레드가 실행을 완료해야만 다른 스레드들이 실행할 수 있습니다

* 4. Vector는 멀티 스레드 환경에서 안전하게 객체를 추가하고 삭제할 수 있습니다

* 5. Vector는 스레드가 1개일때도 동기화를 하기 때문에 ArrayList보다 성능이 떨어집니다

* */