프로그래밍/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와 다름