제네릭 배효철 th1g@nate.com 1
목차 제네릭 컬렉션 백터 ArrayList HashMap LinkedList Collections 클래스 제네릭만들기 컬렉션과자동박싱 / 언박싱 제네릭의장점 2
제네릭 특정타입만다루지않고, 여러종류의타입으로변신할수있도록클래스나메소드를일반화시키는기법 <E>, <K>, <V> : 타입매개변수 요소타입을일반화한타입 제네릭클래스사례 제네릭벡터 : Vector<E> E에특정타입으로구체화 정수만다루는벡터 Vector<Integer> 문자열만다루는벡터 Vector<String> 3
JDK 1.5 에서도입 (2004 년기점 ) 모든종류의데이터타입을다룰수있도록일반화된타입매개변수로클래스나메소드를작성하는기법 C++ 의템플릿 (template) 과동일 정수스택 정수만저장 class Stack<E> {... void push(e element) {... E pop() {...... 제네릭스택 특정타입으로구체화... void push(integer element) {... Integer pop() {......... void push(string element) {... String pop() {...... 문자열스택 20-345 123 10 Good C# C++ Java 문자열만저장 4
5
컬렉션 컬렉션 요소 (element) 라고불리는가변개수의객체들의저장소 객체들의컨테이너라고도불림 요소의개수에따라크기자동조절 요소의삽입, 삭제에따른요소의위치자동이동 고정크기의배열을다루는어려움해소 다양한객체들의삽입, 삭제, 검색등의관리용이 컬렉션클래스사례 Vector, ArrayList, Hashtable, LinkedList, HashMap, HashSet, Stack java.util 패키지에서제공 6
7
컬렉션을위한인터페이스와클래스 Collection<E> Map<K, V> Set<E> List<E> Queue<E> 인터페이스 클래스 HashSet<E> ArrayList<E> Vector<E> LinkedList<E> HashMap<K, V> Stack<E> 8
컬렉션인터페이스가제공하는메소드 9
Vector<E> 의특성 java.util.vector <E> 에서 E 대신요소로사용할특정타입으로구체화 여러객체들을삽입, 삭제, 검색하는컨테이너클래스 배열의길이제한극복 원소의개수가넘쳐나면자동으로길이조절 Vector 에삽입가능한것 객체, null 기본타입은박싱 / 언박싱으로 Wrapper 객체로만들어저장 Vector 에객체삽입 벡터의맨뒤에객체추가 벡터중간에객체삽입 Vector 에서객체삭제 임의의위치에있는객체삭제가능 : 객체삭제후자동자리이동 10
Vector<Integer> 컬렉션내부구성 Vector<Integer> v = new Vector<Integer>(); add() 를이용하여요소를삽입하고 get() 을이용하여요소를검색합니다 11
타입매개변수사용하지않는경우경고발생 Vector 로만사용하면경고발생 Vector<Integer> 나 Vector<String> 등타입매개변수를사용하여야함 12
Vector<E> 클래스의주요메소드 13
14
15
정수값만다루는 Vector<Integer> 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); // 4 삽입 v.add(-1); // -1 삽입 // 벡터속의모든정수더하기 int sum = 0; for(int i=0; i<v.size(); i++) { int n = v.elementat(i); sum += n; System.out.println(" 벡터에있는정수합 : + sum); // 벡터중간에삽입하기 v.add(2, 100); // 4 와 -1 사이에정수 100 삽입 System.out.println(" 벡터내의요소객체수 : " + v.size()); System.out.println(" 벡터의현재용량 : " + v.capacity()); // 모든요소정수출력하기 for(int i=0; i<v.size(); i++) { int n = v.get(i); System.out.println(n); 5 4 100-1 벡터에있는정수합 : 108 16
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) { // Point 객체를요소로만가지는벡터생성 Vector<Point> v = new Vector<Point>(); // 3 개의 Point 객체삽입 v.add(new Point(2, 3)); v.add(new Point(-5, 20)); v.add(new Point(30, -8)); // 벡터에있는 Point 객체모두검색하여출력 for(int i=0; i<v.size(); i++) { Point p = v.get(i); // 벡터에서 i 번째 Point 객체얻어내기 System.out.println(p); // p.tostring() 을이용하여객체 p 출력 (2,3) (-5,20) (30,-8) 17
ArrayList<E> ArrayList<E> 의특성 java.util.arraylist, 가변크기배열을구현한클래스 <E> 에서 E 대신요소로사용할특정타입으로구체화 ArrayList 에삽입가능한것 객체, null 기본타입은박싱 / 언박싱으로 Wrapper 객체로만들어저장 ArrayList 에객체삽입 / 삭제 리스트의맨뒤에객체추가 리스트의중간에객체삽입 임의의위치에있는객체삭제가능 벡터와달리스레드동기화기능없음 다수스레드가동시에 ArrayList에접근할때동기화되지않음 개발자가스레드동기화코드작성 18
ArrayList<String> 컬렉션의내부구성 ArrayList<String> = new ArrayList<String>(); add() 를이용하여요소를삽입하고 get() 을이용하여요소를검색합니다 19
ArrayList<E> 클래스의주요메소드 20
21
22
ArrayList 에문자열을달기 import java.util.*; public class ArrayListEx { 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.print(" 이름을입력하세요 >>"); String s = scanner.next(); // 키보드로부터이름입력 a.add(s); // ArrayList 컬렉션에삽입 // ArrayList 에들어있는모든이름출력 for(int i=0; i<a.size(); i++) { // ArrayList 의 i 번째문자열얻어오기 String name = a.get(i); System.out.print(name + " "); // 가장긴이름출력 int longestindex = 0; for(int i=1; i<a.size(); i++) { if(a.get(longestindex).length() < a.get(i).length()) longestindex = i; System.out.println("\n 가장긴이름은 : " + a.get(longestindex)); 이름을입력하세요 >>Mike 이름을입력하세요 >>Jane 이름을입력하세요 >>Ashley 이름을입력하세요 >>Helen Mike Jane Ashley Helen 가장긴이름은 : Ashley 23
HashMap<K,V> HashMap<K,V> 키 (key) 와값 (value) 의쌍으로구성되는요소를다루는컬렉션 java.util.hashmap K는키로사용할요소의타입, V는값으로사용할요소의타입지정 키와값이한쌍으로삽입 키는해시맵에삽입되는위치결정에사용 값을검색하기위해서는반드시키이용 삽입및검색이빠른특징 요소삽입 : put() 메소드 요소검색 : get() 메소드 예 ) HashMap<String, String> 생성, 요소삽입, 요소검색 HashMap<String, String> h = new HashMap<String, String>(); h.put("apple", " 사과 "); // "apple" 키와 " 사과 " 값의쌍을해시맵에삽입 String kor = h.get("apple"); // "apple" 키로값검색. kor는 " 사과 24
HashMap<String, String> 의내부구성과 put(), get() 메소드 HashMap<String, String> map = new HashMap<String, String>(); 25
HashMap<K,V> 의주요메소드 26
27
HashMap 을이용하여영어단어와한글단어를쌍으로저장하고검색하는사례 import java.util.*; public class HashMapDicEx { public static void main(string[] args) { // 영어단어와한글단어의쌍을저장하는 HashMap 컬렉션생성 HashMap<String, String> dic = new HashMap<String, String>(); // 3 개의 (key, value) 쌍을 dic 에저장 dic.put("baby", " 아기 "); // "baby" 는 key, " 아기 " 은 value dic.put("love", " 사랑 "); dic.put("apple", " 사과 "); // dic 컬렉션에들어있는모든 (key, value) 쌍출력 Set<String> keys = dic.keyset(); // key 문자열을가진 Set 리턴 Iterator<String> it = keys.iterator(); while(it.hasnext()) { String key = it.next(); String value = dic.get(key); System.out.println("(" + key + "," + value + ")"); // 영어단어를입력받고한글단어검색 Scanner scanner = new Scanner(System.in); for(int i=0; i<3; i++) { System.out.print(" 찾고싶은단어는?"); String eng = scanner.next(); System.out.println(dic.get(eng)); (love, 사랑 ) (apple, 사과 ) (baby, 아기 ) 찾고싶은단어는?apple 사과찾고싶은단어는?babo null 찾고싶은단어는?love 사랑 babo 를해시맵에서찾을수없기때문에 null 리턴 28
HashMap 을이용하여자바과목의점수를기록관리하는코드작성 import java.util.*; public class HashMapScoreEx { public static void main(string[] args) { // 사용자이름과점수를기록하는 HashMap 컬렉션생성 HashMap<String, Integer> javascore = new HashMap<String, Integer>(); while(it.hasnext()) { String name = it.next(); int score = javascore.get(name); System.out.println(name + " : " + score); // 5 개의점수저장 javascore.put(" 한홍진 ", 97); javascore.put(" 황기태 ", 34); javascore.put(" 이영희 ", 98); javascore.put(" 정원석 ", 70); javascore.put(" 한원선 ", 99); System.out.println("HashMap 의요소개수 :" + javascore.size()); HashMap 의요소개수 :5 한원선 : 99 한홍진 : 97 황기태 : 34 이영희 : 98 정원석 : 70 29 // 모든사람의점수출력. // javascore 에들어있는모든 (key, value) 쌍출력 // key 문자열을가진집합 Set 컬렉션리턴 Set<String> keys = javascore.keyset(); // key 문자열을순서대로접근할수있는 Iterator 리턴 Iterator<String> it = keys.iterator();
HashMap 을이용한학생정보저장 import java.util.*; class Student { // 학생을표현하는클래스 int id; String tel; public Student(int id, String tel) { this.id = id; this.tel = tel; public class HashMapStudentEx { public static void main(string[] args) { // 학생이름과 Student 객체를쌍으로저장하는 HashMap 컬렉션생성 HashMap<String, Student> map = new HashMap<String, Student>(); // 3 명의학생저장 map.put(" 황기태 ", new Student(1, "010-111-1111")); map.put(" 한원선 ", new Student(2, "010-222-2222")); map.put(" 이영희 ", new Student(3, "010-333-3333")); System.out.println("HashMap 의요소개수 :" + map.size()); HashMap 의요소개수 :3 한원선 : 2 010-222-2222 황기태 : 1 010-111-1111 이영희 : 3 010-333-3333 // 모든학생출력. map 에들어있는모든 (key, value) 쌍출력 // key 문자열을가진집합 Set 컬렉션리턴 Set<String> names = map.keyset(); 출력된결과는삽입된결과와다르다는점을기억하기바람 // key 문자열을순서대로접근할수있는 Iterator 리턴 Iterator<String> it = names.iterator(); while(it.hasnext()) { String name = it.next(); // 다음키. 학생이름 Student student = map.get(name); System.out.println(name + " : " + student.id + " " + student.tel); 30
LinkedList<E> LinkedList<E> 의특성 java.util.linkedlist E 에요소로사용할타입지정하여구체와 List 인터페이스를구현한컬렉션클래스 Vector, ArrayList 클래스와매우유사하게작동 요소객체들은양방향으로연결되어관리됨 요소객체는맨앞, 맨뒤에추가가능 요소객체는인덱스를이용하여중간에삽입가능 맨앞이나맨뒤에요소를추가하거나삭제할수있어스택이나큐로사용가능 31
LinkedList<String> 의내부구성과 put(), get() 메소드 LinkedList<String> l = new LinkedList<String>(); 32
Collections Collections 클래스 java.util 패키지에포함 컬렉션에대해연산을수행하고결과로컬렉션리턴 모든메소드는 static 타입 ( 정적함수 ) 주요메소드 컬렉션에포함된요소들을소팅하는 sort() 메소드 요소의순서를반대로하는 reverse() 메소드 요소들의최대, 최솟값을찾아내는 max(), min() 메소드 특정값을검색하는 binarysearch() 메소드 33
Collections 클래스의활용 문자열정렬, 반대로정렬, 이진검색등 import java.util.*; public class CollectionsEx { static void printlist(linkedlist<string> l) { Iterator<String> iterator = l.iterator(); while (iterator.hasnext()) { String e = iterator.next(); String separator; if (iterator.hasnext()) separator = "->"; else separator = "\n"; System.out.print(e+separator); public static void main(string[] args) { LinkedList<String> mylist = new LinkedList<String>(); mylist.add(" 트랜스포머 "); mylist.add(" 스타워즈 "); mylist.add(" 매트릭스 "); mylist.add(0," 터미네이터 "); mylist.add(2," 아바타 "); Collections.sort(myList); // 요소정렬 printlist(mylist); // 정렬된요소출력 Collections.reverse(myList); // 요소의순서를반대로 printlist(mylist); // 요소출력 int index = Collections.binarySearch(myList, " 아바타 ") + 1; System.out.println(" 아바타는 " + index + " 번째요소입니다."); 소팅된순서대로출력 거꾸로출력 매트릭스 -> 스타워즈 -> 아바타 -> 터미네이터 -> 트랜스포머트랜스포머 -> 터미네이터 -> 아바타 -> 스타워즈 -> 매트릭스아바타는 3 번째요소입니다. 34
제네릭만들기 제네릭클래스와인터페이스 val 의타입은 T 클래스나인터페이스선언부에일반화된타입추가 public class MyClass<T> { T val; void set(t a) { val = a; T get() { return val; T 타입의값 a 를 val 에지정 T 타입의값 val 리턴 제네릭클래스 MyClass 선언, 타입매개변수 T 제네릭클래스레퍼런스변수선언 MyClass<String> s; MyClass<Integer> s; 35 public class MyClass<T> { T val; void set(t a) { val = a; T get() { return val; T 가 String 으로구체화 public class MyClass<String> { String val; // 변수 val 의타입은 String void set(string a) { val = a; // String 타입의값 a 를 val 에지정 String get() { return val; // String 타입의값 val 을리턴
컬렉션과자동박싱 / 언박싱 제네릭의타입매개변수에기본타입은사용할수없음 Vector<int> vi = new Vector<int>(); // 컴파일오류. int 사용불가 Wrapper 클래스를사용하여박싱 / 언박싱후기본타입을사용 Vector<Integer> vi = new Vector<Integer>(); // 정상코드 기본형타입 byte short int long float double char boolean void wrapper class Byte Short Integer Long Float Double Charater Boolean Void 36
컬렉션과자동박싱 / 언박싱 JDK 1.5 이전 기본타입데이터를 Wrapper 클래스를이용하여객체로만들어사용 Vector<Integer> v = new Vector<Integer>(); v.add(new Integer(4)); 컬렉션으로부터요소를얻어올때, Wrapper 클래스로캐스팅필요 Integer n = (Integer)v.get(0); int k = n.intvalue(); // k = 4 JDK 1.5 부터 자동박싱 / 언박싱이작동하여기본타입값사용가능 Vector<Integer> v = new Vector<Integer> (); v.add(4); // 4 new Integer(4) 로자동박싱 int k = v.get(0); // Integer 타입이 int 타입으로자동언박싱, k = 4 제네릭의타입매개변수를기본타입으로구체화할수는없음 Vector<int> v = new Vector<int> (); // 오류 37
제네릭의장점 컬렉션과같은컨테이너클래스에유연성을해치지않으며 type-awareness 를첨가 메소드에 type-awareness 첨가 컴파일시에타입이결정되어보다안전한프로그래밍가능 개발시다운캐스팅 ( 타입캐스팅 ) 절차불필요 런타임타입충돌문제방지 ClassCastException 방지 38