본문 바로가기
Programming/Java프로그래밍및실습

[자프실] 7. 컬렉션과 제네릭

by Lizardee 2024. 1. 7.
7.1 컬렉션과 제네릭 개념
컬렉션의 중요성과 개념
  • 컬렉션: 요소(element)라고 불리는 가변 개수의 객체들의 저장

 

컬렉션을 위한 자바 인터페이스와 클래스

컬렉션 자바 인터페이스와 클래스

 

컬렉션의 특징
  • 컬렉션은 제네릭(generics)이라는 기법으로 구현되어 있다.
  • 컬렉션의 요소는 객체들만 가능하다.

 

제네릭의 기본 개념
  • 제네릭: 모든 종류의 타입을 다룰 수 있도록, 클래스나 메소드를 일반화된 타입 매개 변수(generic type)를 이용하여 선언하는 기법

 

제네릭 타입 매개 변수

: 컬렉션 클래스에서 타입 매개 변수로 사용하는 문자는 다른 변수와 혼동을 피하기 위해 일반적으로 하나의 대문자를 사용한다.

 


7.2 제네릭 컬렉션 활용
Vector<E>

: 배열을 가변 크기로 다룰 수 있게 하고, 객체의 삽입, 삭제, 이동이 쉽도록 구성한 컬렉션 클래스

  • 벡터는 삽입되는 요소의 개수에 따라 자동으로 크기를 조절하고, 요소의 삽입과 삭제에 따라 자동으로 요소들의 자리를 이동한다.

 

  • 벡터 생성: Vector< > v = new Vector< >( );
Vector<Integer> v = new Vector<Integer>();  // 정수만 사용 가능한 벡터

Vector<String> StringVector = new Vector<String>();  // 문자열 벡터
  • 벡터에 요소 삽입: add() 
v.add(Intger.valueOf(5));
v.add(5);  // 자동 박싱

 

  • 벡터 내의 요소 알아내기
Integer obj = v.get(1);  // 벡터의 1번째 요소를 얻어낸다.
int i = obj.intValue();  // obj에 있는 정수를 알아낸다.
  • 벡터의 크기와 용량 알아내기
int Ien = v.size();  // 벡터의 크기: 벡터에 존재하는 요소 객체 수
int cap = v.capacity();  // 벡터의 용량
  • 벡터에서 요소 삭제: v.remove( )
v.remove(1);  // 인덱스 1의 위치에 있는 요소 삭제

 

컬렉션과 자동 박싱/언박싱
// 예제 7-1: 정수만 다루는 Vector<Integer> 제네릭 벡터

import java.util.Scanner;
import java.util.Vector;

public class VectorEx {
	public static void main(String[] args) {
		// 정수  값만 다루는 제네릭 벡터 생성
		Vector<Integer> v = new Vector<Integer>();
		v.add(5);  // 5 삽입
		v.add(4);  
		v.add(-1);
		
		// 벡터 중간에 삽입하기
		v.add(2,100);  // 4와 -1 사이에 정수 100 삽입
		
		System.out.println("벡터 내의 요소 객체 수: " + v.size());  // 크기 4
		System.out.println("벡터의 현재 용량: " + v.capacity());  // 벡터의 디폴트 용량 10
		
		// 모든 요소 정수 출력하기
		for(int i=0; i<v.size(); i++) {
			int n = v.get(i);  // 벡터의 i번째 정수
			System.out.println(n);
		}
		
		// 벡터 속의 모든 정수 더하기
		int sum=0;
		for(int i=0; i<v.size(); i++) {
			sum += v.elementAt(i);  // 벡터의 i번째 정수
		}
		System.out.println("벡터에 있는 정수 합: " + sum);
	}
}
  • Vector<Integer> v = new Vector<Integer>();
  • v.add(1);
  • v.size();  // 벡터 내의 요소 객체 수
  • v.capacity();  // 벡터의 디폴트 용량
  • v.get(i);  // 벡터의 i번째 정수
  • v.element(i);  // 벡터의 i번째 정수

 

ArrayList<E>
// 예제 7-3: 문자열만 다루는 ArrayList<String>

import java.util.*;

public class Ex7_3 {
	public static void main(String[] args) {
		// 문자열만 삽입가능한 ArrayList 컬렉션
		ArrayList<String> a = new ArrayList<String>();
		
		// 키보드로부터 4개의 이름 입력받아 ArrayList에 삽입
		Scanner scanner = new Scanner(System.in);
		for(int i=0; i<4; i++) {
			System.out.println("이름을 입력하세요>>");
			String s = scanner.next();
			a.add(s);  // ArrayList 컬렉션에 삽입
		}
		
		// ArrayList에 들어 있는 모든 이름 출력
		for(int i=0; i<a.size(); i++) {
			String name = a.get(i);
			System.out.print(name + " ");
		}
		
		// 가장 긴 이름 출력
		int longestIndex =  0;  // 현재 가장 긴 이름이 있는 ArrayList 내의 인덱스
		for(int i=0; i<a.size(); i++) {
			if(a.get(longestIndex).length() < a.get(i).length())  // 이름 길이 비교
				longestIndex = i;
		}
		System.out.println("\n가장 긴 이름은: " + a.get(longestIndex));
		scanner.close();
	}
}

 

컬렉션의 순차 검색을 위한 Iterator
import java.util.*;

public class Ex7_4 {
	public static void main(String[] args) {
		// 정수 값만 다루는 제네릭 벡터 생성
		Vector<Integer> v = new Vector<Integer>();
		v.add(5);  // 0
		v.add(4);  // 1
		v.add(-1);  // 2
		v.add(2,100);  // 4와 1 사이에 정수 100 삽입
		
		// Iterator를 이용한 모든 정수 출력하기
		Iterator<Integer> it = v.iterator();  // Iterator 객체 얻기
		while(it.hasNext()) {
			int n = it.next();
			System.out.println(n);
		}
		
		// Iterator를 이용하여 모든 정수 더하기
		int sum=0;
		it = v.iterator();  // Iterator 객체 얻기
		while(it.hasNext()){
			int n = it.next();
			sum += n;
		}
		System.out.println("벡터에 있는 정수 합: " + sum);
	}
}

 

HashMap<K, V>

: 키(key)와 값(value)의 쌍으로 구성되는 요소를 다른다.

  • K: '키'로 사용할 데이터 타입의 타입 매개변수
  • V: '값'으로 사용할 데이터 타입의 타입 매개변수
import java.util.*;

public class Ex7_4 {
	public static void main(String[] args) {
		// 정수 값만 다루는 제네릭 벡터 생성
		Vector<Integer> v = new Vector<Integer>();
		v.add(5);  // 0
		v.add(4);  // 1
		v.add(-1);  // 2
		v.add(2,100);  // 4와 1 사이에 정수 100 삽입
		
		// Iterator를 이용한 모든 정수 출력하기
		Iterator<Integer> it = v.iterator();  // Iterator 객체 얻기
		while(it.hasNext()) {
			int n = it.next();
			System.out.println(n);
		}
		
		// Iterator를 이용하여 모든 정수 더하기
		int sum=0;
		it = v.iterator();  // Iterator 객체 얻기
		while(it.hasNext()){
			int n = it.next();
			sum += n;
		}
		System.out.println("벡터에 있는 정수 합: " + sum);
	}
}

 

▶ 해시맵 생성

HashMap<String, String> h = new HashMap<String, String>();

 

▶ 해시맵에 요소 삽입

h.put("baby", "아기");  // "baby"가 키이고, "아기"는 값이다.

 

▶ '키'로 '값' 읽기

String kor = h.get("baby");

 

▶ '키'로 요소 삭제

h.remove("baby");

 

▶ 요소 개수 알아내기

input n = h.size();  // 현재 h 내에 있는 요소의 개수 리턴

 

▶ 해시맵의 전체 검색

Set<String> keys = h.keySet();  // 해시맵 h에 있는 모든 키를 Set 컬렉션으로 리턴
Iterator<String> it = keys.iterator();  // Set에서 문자열을 검색할 수 있는 Iterator 리턴
while(it.hasNext()){
  String key = it.next(); // 키
  String value = h.get(key);  // 값
  System.out.println("(" + key + "," + value + ")");  // 키와 값의 쌍 출력
}

 

// 예제 7-5: HashMap<String, String>로 (영어, 한글) 단어 쌍을 저장하고 검색하기

import java.util.*;

public class Ex7_5 {
	public static void main(String[] args) {
		// 영어 단어와 한글 단어 쌍을 저장하는 HashMap 컬렉션 생성
		HashMap<String, String> dic = new HashMap<String, String>();
		
		// 3개의 (key, value) 쌍을 dic에 저장
		dic.put("baby", "아기");
		dic.put("love", "사랑");
		dic.put("apple", "사과");
		
		// dic 해시맵에 들어 있는 모든 (key, value) 쌍 출력
		Set<String> keys = dic.keySet();  // 모든 키를 Set 컬렉션에 받아옴
		Iterator<String> it = keys.iterator();  // Set에 접근하는 Iterator 리턴
		while(it.hasNext()) {
			String key = it.next();  // 키
			String value = dic.get(key);  // 값
			System.out.println("(" + key + "," + value + ")");
		}
		System.out.println();
		
		// 사용자로부터 영어 단어를 입력받고 한글 단어 검색
		Scanner scanner = new Scanner(System.in);
		for(int i=0; i<3; i++) {
			System.out.print("찾고 싶은 단어는?");
			String eng = scanner.next();
			
			// 해시맵에서 '키' eng의 '값' kor 검색
			String kor = dic.get(eng);
			if(kor == null)
				System.out.println(eng + "는 없는 단어입니다.");
			else
				System.out.println(kor);
		}
	}
}

 


7.3 제네릭 만들기
제네릭 클래스
// 제네릭 클래스 작성

public class MyClass<T> {
  T val;  // 변수 val의 타입은 T
  void set(T a){
    val = a;  // T 타입의 값 a를 val에 지정
  }
  T get() {
    return val;  // T 타입의 값 val 리턴
  }
}

 

// 제네릭 객체 생성 및 활용

MyClass<String> s = new MyClass<String>();  // 제네릭 타입 T를 String으로 구체화
s.set("hello");
System.out.println(s.get());  // hello 출력

MyClass<Integer> n = new MyClass<Integer>();  // 제네릭 타입 T를 Integer로 구체화
n.set(5);
System.out.println(n.get());  // 숫자 5 출력

 

// 예제 7-6: 스택을 제네릭 클래스로 작성하고, String과 Integer형 스택을 사용하는 예

class GStack<T>{
	int tos;
	Object [] stck;  // 스택에 저장된 요소의 개수
	public GStack() {
		tos = 0;
		stck = new Object[10];
	}
	public void push(T item) {
		if(tos == 10)  // 스택이 꽉 차서 더 이상 요소를 삽입할 수 없음
			return;
		stck[tos] = item;
		tos++;
	}
	public T pop() {
		if(tos == 0)
			return null;
		tos--;
		return (T)stck[tos];  // 타입 매개 변수 타입으로 캐스팅
	}
}

public class Ex7_6 {
	public static void main(String[] args) {
		GStack<String> stringStack = new GStack<String>();  // String 타입의 GStack 생성
		stringStack.push("seoul");
		stringStack.push("busan");
		stringStack.push("LA");
		
		for(int n=0; n<3; n++)
			System.out.println(stringStack.pop());
		
		GStack<Integer> intStack = new GStack<Integer>();  // Integer 타입의 GStack 생성
		intStack.push(1);
		intStack.push(3);
		intStack.push(5);
		
		for(int n=0; n<3; n++)
			System.out.println(intStack.pop());  // intStack 스택에 있는 3개의 정수 팝
	}
}