1. 컬렉션의 개념
배열은 여러 개의 데이터를 다루는 데 편리한 자료 구조이지만, 삽입 삭제가 빈번하고, 데이터의 크기를 예측할 수 없는 응용프로그램에서 사용하기에는 불편한 자료구조입니다.
예를 들어 전화번호부와 같이 번호의 삽입, 삭제가 비번하게 이루어지는 경우는 고정 크기의 배열을 사용한다면 코드 작성에 상당한 어려움이 따르게 됩니다.
배열(Array)
- 고정 크기 이상의 객체를 관리할 수 없다.
- 배열의 중간에 객체가 삭제되면 응용프로그램에서 자리를 옮겨야 한다.
컬렉션(Collection)
- 가변 크기로서 객체의 개수를 염려할 필요 없다.
- 컬렉션 내의 한 객체가 삭제되면 컬렉션이 자동으로 자리를 옮겨준다.
이처럼 컬렉션은 배열이 가진 고정 크기의 단점을 극복하기 위해 객체들을 쉽게 삽입, 삭제, 검색할 수 있는 가변 크기의 컨테이너(Container)입니다.
java.util 패키지는 다양한 컬렉션 인터페이스와 컬렉션 클래스를 제공합니다. 패키지의 제공 목록은 다음 그림과 같습니다.
컬렉션 클래스는 개발자가 바로 사용 가능합니다.
- Vecter<E>, ArrayList<E> : 가변 크기의 배열을 구현
- LinkedList<E> : 노드들이 링크로 연결되는 리스트를 구현
- Stack<E> : 스택을 구현
- HashSet<E> : 집합을 구현
위의 5가지는 모두 Collectioin<E>를 상속받고, 단일 클래스의 객체만을 요소로 다루는 공통점이 있습니다.
그리고 Hashmap<K, V>는 해시 자료구조를 구현하였으며 '키(K)'와 '값(V)'의 쌍으로 이루어지는 데이터를 저장하고, '키'로 쉽게 검색하도록 만든 컬렉션입니다.
2. 컬렉션의 특징
2-1. 제네릭
컬렉션은 제네릭(generics)라는 기법으로 만들어져 있습니다. 컬렉션 클래스의 이름에는 <E>, <K>, <V>를 사용합니다. 이들은 '타입 매개변수'라고 하며, Vecter<E>에서 E대신 Integer와 같은 구체적인 타입을 지정하면, Vecter<Integer>는 정수 값만 저장하는 벡터로, Vecter<String>은 문자열만 저장하는 벡터로 사용할 수 있습니다.
이렇게 하는 이유는 타입 독립적인 코드를 작성하기 위해서이며, 특정 타입만 다루지 않고 여러 종류의 타입으로 변신할 수 있도록, 컬렉션을 일반화시키기 위해 <E>를 사용합니다. 그래서 E를 제네릭 타입이라고 부릅니다.
또한 컬렉션의 요소는 객체들만 사용 가능합니다. int, char, double과 같은 원시 타입(primitive type)은 사용 불가하고 Integer, String, Double같은 참조 타입(reference type)만 사용 가능합니다.
Vecter<int> v = new Vecter<int>(); // 컴파일 오류발생. int 사용불가
Vecter<Integer> v = new Vecter<Integer>(); // 정상 작동
2-2. 제네릭의 기본 개념
제네릭은 모든 종류의 타입을 다룰 수 있도록, 클래스나 메소드를 타입 매개변수(generic type)을 이용하여 선언하는 기법입니다. 자바에서 제네릭은 클래스 코드를 찍어내듯이 생산할 수 있도록 일반화(generic)시키는 도구입니다.
class Stack<E> {
void push(E element) {...}
E pop() {...}
}
Stack<E>에서 E에 구체적인 타입을 지정하면, 지정된 타입만 다룰 수 잇는 구체화된(specialized) 스택이 됩니다.
Stack<Integer>는 Integer 타입만 다루는 스택이 되고, Stack<Point>는 Point타입의 객체만 푸시(push)하고 팝(pop)할 수 있는 스택이 됩니다.
2-3. 제네릭 타입 매개변수
컬렉션 클래스에서 타입 매개변수로 사용하는 문자는 다른 변수와 혼동을 피하기 위해 일반적으로 하나의 대문자를 사용합니다.
- E : Element를 의미하며 컬렉션에서 요소임을 나타냄
- T : Type을 의미
- V : Value를 의미
- K : Key를 의미
3. 제네릭 컬렉션 활용
3-1. Vector<E>
벡터는 배열을 가변 크기로 다룰 수 잇게 하고, 객체의 삽입, 삭제, 이동이 쉽도록 구성한 컬렉션 케이스입니다. 벡터는 삽입되는 요소의 개수에 따라 자동으로 크기를 조절하고, 요소의 삽입과 삭제에 따라 자동으로 요소들의 자리를 이동합니다.
메소드 | 설명 |
boolean add(E element) | 벡터의 맨 뒤에 element 추가 |
void add(int index, E element) | 인덱스 index에 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(Object o) | 인덱스 index의 요소 삭제 |
boolean remove(Object o) | 객체 o와 같은 첫 번째 요소를 벡터에서 삭제 |
void removeAllElements() | 벡터의 모든 요소를 삭제하고 크기를 0으로 만듦 |
int size() | 벡터가 포함하는 요소의 개수 리턴 |
Object[] toArray() | 벡터의 모든 요소를 포함하는 배열 리턴 |
3-1-1. 벡터 생성
벡터를 생성할 때, Vector<E>의 E에 요소로 사용할 타입을 지정해야 합니다. 정수 값만 삽입 가능한 벡터를 만들때는 E에 Integer를 지정하여 벡터를 생성합니다.
Vector<Integer> v = new Vector<Intger>();
벡터 v는 int, char, double등의 기본 타입은 E에 사용할 수 없습니다.
Vector<int> v = new Vector<int>();
레퍼런스 변수 선언과 벡터 생성을 분리하여 코드를 만들 수 있으며, 문자열만 다루는 벡터는 아래처럼 생성이 가능합니다.
Vector<String> stringVector;
StringVector = new Vector<String>();
3-1-2. 벡터에 요소 삽입
add() 메소드를 이용하면 벡터의 끝이나 중간에 요소를 삽입할 수 있습니다.
v.add(5);
v.add(4);
v.add(-1);
자동 박싱에 의해 int 타입의 정수는 자동으로 Integer 객체로 변환되어 삽입되었습니다. 하지만 이제 v에는 Integer타입 이외의 다른 타입의 변수는 삽입할 수 없습니다.
v.add(null);
벡터에는 null도 삽입할 수 있습니다.
v.add(2, 100);
add()를 이용하여 벡터의 중간에 객체를 삽입하였습니다.
3-1-3. 벡터 내의 요소 알아내기
벡터 내에 존재하는 요소를 알아내기 위해서 get()이나 elementAt() 메소드를 이용할 수 있습니다.
Vector<Integer> v = new Vector<Integer>();
v.add(5);
v.add(4);
v.add(-1);
get()이나 elementAt() 메소드는 인자로 주어진 인덱스에 있는 Integer 객체를 리턴합니다.
Integer obj = v.get(1); // 벡터의 1번째 Integer 객체를 얻어낸다.
int i = obj.intValue(); // obj에 있는 정수를 알아낸다. 이 값은 4
앞의 두 문장은 다음과 같이 사용할 수 있습니다.
int i = v.get(1);
전체 코드)
package practice_java;
import java.util.Vector;
public class prac1 {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(5);
v.add(4);
v.add(-1);
int i = v.get(1);
System.out.println(i);
}
}
결과)
4
3-1-4. 벡터의 크기와 용량 알아내기
벡터의 크기란 벡터에 들어 있는 요소의 개수를 말하며, 벡터의 용량이란 수용할 수 있는 크기를 말합니다.
벡터의 크기는 size() 메소드를 사용합니다.
int len = v.size();
벡터의 용량은 capacity() 메소드를 호출합니다.
int cap = v.capacity();
3-1-5. 벡터에서 요소 삭제
벡터 내에 임의의 인덱스에 있는 요소를 remove() 메소드를 사용하여 삭제할 수 있습니다.
v.remove(1);
예시)
package practice_java;
import java.util.Vector;
public class prac1 {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(5);
v.add(4);
v.add(-1);
v.remove(1); // 인덱스 1의 요소를 삭제
System.out.println(v);
}
}
[5, -1]
벡터에서 모든 요소를 삭제하려면 removeAllElements()를 사용할 수 있습니다.
v.removeAllElements();
3-2. 컬렉션과 자동 박싱/언박싱
컬렉션은 객체들만 요소(element)로 다룬다고 하였습니다. 그래서 기본 타입(primitive type)의 값은 Wrapper 클래스로 객체화 되어 삽입합니다.
package practice_java;
import java.util.Vector;
public class prac1 {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(Integer.valueOf(4));
v.add(Integer.valueOf(-1));
System.out.println(v);
}
}
결과)
[4, -1]
그러나 자동 박싱(auto boxing)에 의해 int 타입의 값을 사용하면 자동으로 Integer 객체로 변환되어 삽입됩니다.
package practice_java;
import java.util.Vector;
public class prac1 {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(4);
v.add(-1);
System.out.println(v);
}
}
결과는 위와 같습니다.
컬렉션으로부터 값을 얻어내는 과정에서는 자동 언박싱(auto unboxing)이 일어납니다. 벡터로 부터 정수 값을 바로 얻어내느 코드를 보겠습니다.
package practice_java;
import java.util.Vector;
public class prac1 {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(4);
v.add(-1);
int k = v.get(0); // 4
System.out.println(k);
}
}
결과)
4
이러한 자동 박싱/언박싱은 모든 컬렉션 클래스에서 작동합니다.
3-3. 자바의 타입 추론 기능
제네릭 컬렉션을 사용하여 객체를 생성하는 문법은 다음과 같습니다.
Vector<Integer> v = new Vector<Integer>();
java 7부터 제네릭의 객체 생성부의 <> 내(다이아몬드 연산자)에 타입 매개변수를 생략하면 컴파일러가 추론하여 타입 매개변수를 찾아줍니다.
Vector<Integer> v = new Vector<>();
java 10은 아예 var 키워드를 도입하여 컴파일러에게 변수 타입을 추론하도록 하는 기능을 더하였습니다.
var v = new Vector<Integer>();
'[WEB]' 카테고리의 다른 글
[Java] 윈도우 자바 환경변수 설정방법 (0) | 2022.09.29 |
---|---|
[Java] 자바 컬렉션 2 (0) | 2022.09.25 |
[Java] 자바 제네릭 클래스, 제네릭 메소드 (0) | 2022.09.24 |
[Java] Object 클래스 (0) | 2022.09.23 |
[Java] 인터페이스와 추상 클래스 (0) | 2022.09.23 |