자바_기본_제네릭과_컬렉션

Posted by Start Bootstrap on May 19, 2020 · 6 mins read

[자바 기본] 7. 제네릭과 컬렉션

7.1 컬렉션의 개념

컬렉션 : 자바의 컬렉션은 제네릭 기법으로 구현된 자바의 자료구조이며, 가변 크기의 컨테이너이고, 여기에 관리되는 객체들을 요소라고 불린다.

컬렉션의 특징

  1. 제네릭이라는 기법으로 구현되어 있다 : 따라서 ‘타입 매개 변수’라고 불리는 요소가 항상 존재 한다. 에 원하는 타입을 넣으면 그 타입의 객체들을 저장하는 컬렉션이 되며 는 다양한 타입의 컬렉션으로 변할 수 있기 때문에 제네릭 타입이라고 불린다.
  2. 컬럭션의 요소는 객체들만 가능하다.

제네릭 : 제네릭은 모든 종류의 타입을 다룰 수 있도록 일반화된 타입 매개변수로 클래스나 메소드를 선언하는 기법을 의미한다.

제네릭 타입 매개 변수

  • E : Element를 의미하여 컬렉션에서 요소를 표시할
  • T : Type을 의미
  • K : Key
  • V : Value

7.2 제네릭 컬렉션 활용

  • Vector

List 인터페이스를 구현한 클래스로서 가변 개수의 배열이 필요할때 적합하다.

-벡터의 용량 설정

Vector<Integer> v = new Vector<Integer>(5); // 초기 용량이 5인 벡터

-요소삽입

v.add(new Integer(5));

이런 식으로 해야하지만 자바 5이상부터 자동박싱이 적용되어 아래처럼 기본데이터로 입력해도 객체로 변환된다.

v.add(5);

백터에는 null도 삽입 가능하다.

v.add(null);

-컬렉션과 자동 박싱/ 언방식

박싱 : 기본 데이터 타입에서 -> 클래스로 (더 높은 수준)

언박싱 : 클래스에서 -> 기본 데이터 타입으로 (낮은 수준으로)

  • ArrayList

Vector와 비슷하지만 차이점은 ArrayList는 스레드 간에 동기화를 지원하지 않는다. 따라서 다수의 스레드가 동시에 ArrayList 요소에 삽입하거나 삭제할때 충돌이 발생.

  • 컬렉션의 순차 검색을 위한 Iterator

리스트 모양의 컬렉션에서요소를 순차적으로 검색할 떄 사용된다.

Vector<Integer> v = new Vector<Integer();
Iterator<Integer> it = v.iterator();
메소드 설명
boolean hasNext() 다음 반복에서 사용될 요소가 있으면 true리턴
E next() 다음요소 리턴
void remove() 마지막으로 리턴된 요소 제거
  • HashMap<K,V>

키와 값의 쌍으로 구성되는 요소를 다루는 컬렉션이다.

  • LinkedList

LinkedList는 요소들을 양방향으로 연결하여 관라하는 점을 제외하고는 Vector와 ArrayList와 매우 유사하다. 또한 LinkedList는 맨 앞과 뒤를 가리키는 head와 tail 래퍼런스를 가지고있어 좀더 직관적으로 요소에 접근할 수 있다.

  • Collections 클래스 활용
  1. sort() - 오름차순정렬
  2. reverse() - 요소를 반대 순으로
  3. max() , min() - 요소들의 최대값과 최소값 찾기
  4. binarySearch - 이진 검색

7.3 제네릭 만들기

제네릭 클래스 또는 인터페이스를 선언하는 방법은 기존의 클래스나 인터페이스 선언방법과 유사하다. 단 클래스나 인터페이스 이름 다음에 일반화된 타입의 타입 매개 변수를 ‘<’ 와 ‘>’ 사이에 추가한다.

  • 제네릭 클래스 작성
public class MyClass<T>{
	T val;
	void set(T a){
		val = a;
	}
	T get(){
		return val;
	}
}
  • 제네릭 클래스 레퍼런스 변수 선언

제네릭 클래스의 래퍼런스 변수를 선언할 떄는 다음과 같이 타입 매개 변수에 구체적인 타입을 적는다.

MyClass<String> s;
List<Integer> li;
Vector<String> vs;
  • 제네릭 객체 생성 - 구체화

객체를 생성화는 과정을 의미한다.

MyClass<String> s = new MyClass<String>(); // 제네릭 타입 T에 String을 지정함

클래스 선언시에 안에 구체적인 타입을 명시해주면 그 타입만을 다루는 클래스가 된다.

public class MyClass<String>{
 //String만을 다루는 클래스
}

  • 타입 매개 변수

제네릭 클래스를 작성할 떄, 제네릭 클래스 내에서 제네릭 타입을 사용하여 객체를 생성하는 것은 불가능하다.

  • 제네릭과 배열

제네릭에서는 배열에 대한 제한을 두고 있다. 따라서 제네릭에 배열을 선언 할 수 없다.

  • 제네릭 메소드

클래스나 인터페이스에 메소드만 제네릭으로 구현할 수도 있다.

class GenericMethodEx{
	static <T> void toStack(T[] a, GStack<T> gs){
		// 메소드의 인자를 통해 타입을 유추할 수 있어 타입을 명시하지 않아도됨
	}
}

Object[] oa = new Object[100];
GStack<Object> gso = new GStack<Object>();
GenericMethodEx.toStack(oa,gso); // 타입 매개변수 T를 Object로 유추

String[] sa = new String[100];
GStack<String> gss = new GStack<String>();
GenericMethodEx.toStack(sa,gss); // 타입 매개변수 T를 String으로 유추

다른 타입이 섞여 있는 둘중 슈퍼클래스로 유추한다. 아래는 그 예이다.

GenericMethodEx.toStack(sa,gso); // Object가 String의 슈퍼 클래스 이므로

  • 제네릭의 장점
  1. 동적으로 타입이 결정되지 않고 컴파일 시에 타입이 결정되므로 보다 안전한 프로그래밍 가능
  2. 런타임 타입 충돌 문제 방지
  3. 개발 시 타입 캐스팅 절차 불필요
  4. ClassCastException 방지