쌓고 쌓다

[JAVA] Collection, Generics, Vector, ArrayList 본문

프로그래밍/java

[JAVA] Collection, Generics, Vector, ArrayList

승민아 2022. 5. 26. 22:39

배열의 문제점

  • 고정된 크기
  • 삽입, 삭제시 위치 조정이 까다로움

 

컬렉션

: 요소(Element)라고 불리는 가변 개수의 객체들의 저장소

  • 객체들의 컨테이너라고도 불림
  • 요소의 개수에 따라 크기 자동 조절
  • 요소의 삽입, 삭제에 따른 요소의 위치 자동 이동 ( 객체의 개수, 자리이동 등 편리 )
  • 다양한 객체들의 삽입, 삭제, 검색 등 관리가 용이

 

(컬렉션 인터페이스와 클래스)

 

컬렉션의 특징

  • 컬렉션은 제네릭(Generics) 기법으로 구현

제네릭

  • 특정 타입만 다루지 않고, 여러 종류의 타입으로 변신할 수 있도록 클래스나 메소드를 일반화 시킴
  • 클래스나 인터페이스 이름에 <E>, <K>, <V> 등이 '타입 매개변수'이며 이것을 포함
  • E :  Element (요소)
  • T : Type
  • V : Value
  • K : Key 를 의미

벡터 Vector<E>의 사용

  • <E>에서 E에 구체적인 타입을 주어 그 타입만 다루는 벡터로 사용함
  • ex) 정수만 다루는 컬렉션 벡터 -> Vector<Integer>
  • ex) 문자열만 다루는 컬렉션 벡터 -> Vector<String>
  • 컬렉션의 요소는 객체만 가능 ( int, char, double 등의 기본 타입으로 구체화 불가 )
Vector<Integer> v = new Vector<Integer>();
// Vector<int> v = new Vector<int>(); <- 컴파일 에러

 

제네릭

: 모든 종류의 클래스 타입을 다룰 수 있도록 일반화된 타입 매개 변수로 클래스(인터페이스)나 메소드를 작성하는 기법

 

제네릭 스택

class Stack<E> {
...
void push( E element ) { ... }
E pop() { ... }
...
}

-> 제네릭 스택을 아래와 같이 특정 타입으로 구체화 한다.

 

정수 스택

...
void push(Integer element) { ... }
Integer pop() { ... }
...

 

문자열 스택

...
void push(String element) { ... }
String pop() { ... }
...

 

다양한 객체를 다루는 Vector

Vector<String> v = new Vector<String>(); // 문자열만 저장
Vector<Integer> v2 = new Vector<Integer>(); // 정수만 저장

 

**** 제네릭 Stack<E> 클래스

-> 상속과 인터페이스 설명 ****

 

Vector<E>

  • 배열을 가변 크기로 다룰 수 있게 하는 컨테이너
    • 길이 제한 없음
    • 요소의 개수가 자리를 넘치면 자동으로 길이를 추가 조절
  • 요소 객체들을 삽입, 삭제, 검색하는 컨테이너
    • 삽입, 삭제에 따라 자동으로 요소의 위치가 조정됨
  • Vector에 삽입 가능한 것
    • 객체, null( v.add(null) )
    • null이 삽입 가능하기에 벡터를 검색할때 null이 존재할 수 있음을 주의!
    • 기본 타입의 값 -> Wrapper 객체로 바꾸어 저장 (자동 박싱)
  • Vector에 객체 삽입
    • 원하는 위치에 객체 삽입 가능
  • Vector에 객체 삭제
    • 임의의 위치에 있는 객체 삭제 가능, 삭제 후 자동 자리이동

 

Vector<Integer> 생성

import java.util.Vector;

public class GenericsTest{
	public static void main(String[] args) {
    	Vector<Integer> v = new Vector<Integer> ();
        Integer i = Integer.valueOf(5);
        v.add(i); // Integer로 넣기
        v.add( Integer.valueOf(4) ); // Integer 함수를 이용해 넣기
        v.add(-1); // 자동 박싱되어 삽입
        v.add(10); // 자동 박싱
        
        for(Integer k : v)
        { System.out.print(k+" "); } // 객체 k만 호출시 .toString 자동 변환되어 String으로 반환됨
       }
}

 

타입 매개변수 사용하지 않는 경우 경고 발생

// Vector v = new Vector(); <-- 타입 매개변수를 사용하지 않아 에러
Vector<Integer> v = new Vector<Integer>();

 

Vector<E> 클래스의 주요 메소드

boolean add(E element) 벡터의 맨 뒤에 element 추가
void add(int index, E element) 인덱스를 지정해 삽입
int capacity() 벡터의 현재 용량 리턴( 현재 개수가 아닌 용량이다)
boolean addAll(Collection<? extends E> c) 컬렉션 c의 모든 요소릴 벡터의 맨 뒤에 추가
void clear() 벡터의 모든 요소 삭제
boolean contains(Object o) 벡터가 지정된 객체 o를 포함하고 있으면 true
E elementAt(int index) 인덱스 index의 요소 리턴
E get(int index) 인덱스 index의 요소 리턴
int indexOf(Object o) o와 같은 첫번째 요소의 인덱스 리턴, 없으면 -1 리턴
boolean isEmpty() 벡터가 비어있으면 true 리턴
E remove(int index) 인덱스 index의 요소 삭제
boolean remove(Object o) 객체 o와 같은 첫번째 요소를 벡터에서 삭제
void removeAllElements() 벡터의 모든 요소를 삭제하고 크기를 0으로 만듦
int size() 벡터가 포함하는 요소의 개수 리턴
Object[] toArray() 벡터의 모든 요소를 포함하는 배열 리턴

 

Vector<Integer> 컬렉션 사용 예제

 

초기 용량 설정 예

Vector<Integer> v = new Vector<Integer>(7);

 

원소 삽입 예

v.add( Integer.valueOf(5) ); // Integer 5 삽입
v.add( 4 ); // int 4가 자동 Integer Boxing 되어 벡터에 들어간다.
v.add( -1 ); // 마찬가지

 

size, capacity 예

int n = v.size(); // n에 3이 들어감 ( 원소 5, 4, -1 순서로 들어가 있음 )
int c = v.capacity(); // c에 7이 들어감 ( 처음 용량 초기화를 7로 했기 때문)

 

요소 중간 삽입 예 

// v.add(5, 100); <--- 현재 size는 3이라 0~3위치에만 삽입이 가능하기에 오류
v.add(2, 100); // 인덱스 2의 위치에 삽입

-> v.size()보다 큰 곳에 삽입 불가능, 오류

 

요소 얻어내기 ( v.get(int index) )

Integer obj = v.get(1) // 인덱스 1인 위치에 원소를 뽑아냄
int i = obj.intValue(); // Intger obj를 int로 변환해 저장 ( int <- unBoxing int로 언박싱 )

 

마지막 요소 얻어내기

int last = v.lastElement();

 

요소 삭제

v.remove(1); // index 1인 원소 삭제
// v.remove(100); // index 100인 원소는 없기에 오류

 

모든 요소 삭제

v.removeAllElements();

 

컬렉션 사용시 자동 박싱/언박싱

Vector<Integer> v = new Vector<int>();
v.add(4); // 4 -> Integer.valueOf(4)로 자동 박싱
int k = v.get(0); // Integer 타입이 int 타입으로 자동 언박싱 되어 k에 4가 들어감

-> 아래와 같이 제네릭의 타입 매개 변수를 기본 자료형으로 구체화할 수는 없음

Vector<int> v = new Vecotr<int>(); // 오류

 

벡터 속의 모든 정수 더하기

int sum = 0;
for(int i=0;i<v.size();i++) {
	int n = v.elementAt(i); // 벡터의 i번째 정수(객체반환), v.get(i)와 같다.
    sum+=n;
}

 

< remove 메소드 사용 주의 >

v.remove(2); // 2번 인덱스 요소를 삭제
v.remove( Integer.valueOf(2) ); // 정수2를 가진 요소 삭제

즉, 객체 레퍼런스를 넣으면 레퍼런스가 가리키는 요소를 삭제함.

 

Vector의 toArray() 메소드

Object arrOb[] = v.toArray();

for(Object k : arrOb)
{
	System.out.print(k+" ");
    // System.out.print(k.toString()+" ");
}
// 원소가 차례대로 출력될 것이다.

for(Object k : arrOb)
{
	System.out.print( v.indexOf(k)+" ");
}
// 해당하는 원소가 존재하는 인덱스가 출력될 것이다.

 

Vector의 Booelan addAll(Collection<> c) 메소드

Vector<Integer> v = new Vector<Integer>();
...
Vector<Integer> w = new Vector<Integer>();
...

v.addAll(w);

for(Integer k : v)
	System.out.print(k+" ");

 

Point 클래스의 객체들을 저장하는 벡터 만들기 예

Point 클래스

import java.util.Vector;
class Point {
	private int x, y;
    public Point(int x, int y) {
    	this.x=x;
        this.y=y;
	}
    
    public String toString() {
    	return "("+x+","+y+")";
        }
}

 

메인 함수

public class PointVectorEx{
	public static void main(String[] args) {
    	Vector<Point> v = new Vector<Point>();
        
        v.add(new Point(2,3));
        v.add(new Point(-5,20));
        v.add(new Point(30,-8));
        
        v.remove(1); // 인덱스 1인 Point(-5,20) 삭제됨
        
       for(int i=0;i<v.size();i++){
       	Point p = v.get(i);
        System.out.println(p);
        }
	}
}

 

출력 결과

(2,3)
(30,-8)

 

컬렉션을 매개변수로 받는 메소드

public void printVector( Vector<Integer> v ) {
	for(int i=0;i<v.size();i++) {
    	int n = v.get(i);
        System.out.println(n);
      }
}

Vector<Integer> v = new Vector<Integer>();
printVector(v);

주의!! 함수 매개변수로 Vector<Integer> v[]로 쓰면 틀림!!

 

ArrayList<E>

ArrayList<String> = new ArrayList<String>();

 

벡터와 거의 동일하다. 가변 크기의 배열을 구현한 것임

  • 요소 삽입, 삭제, 검색 등 벡터 기능과 거의 동일
  • 벡터와 달리 쓰레드 동기화 기능 없음
    • 다수 쓰레드가 동시에 ArrayList에 접근할 때 동기화되지 않음.
    • 개발자가 쓰레드 동기화 코드 작성해야함.

 

사용 예

ArrayList<String> a = new ArrayList<String>(7);
a.add("Hello");
a.add("Hi");
a.add("Java");
int n = a.size(); // <---- Vector와 다른점 : ArrayList에는 capacity() 메소드가 없다.
a.add(2,"Sahni");
String str = a.get(1);
a.remove(1):
a.clear();

-> capacity()가 없다 // vector와 다름

Comments