13주 컬렉션 (Collection) 제네릭스 (Generics) 자바프로그래밍 강원대학교 1/79 Collections - 많은 데이터를 저장하는 방법 배열과 ArrayList 외에도 많은 클래스가 있다. 이들의 특징과 용도를 알아본다. 자바프로그래밍 강원대학교 2/79 LinkedList 먼저 구체적 예를 하나 살펴보자 자바프로그래밍 강원대학교 3/79 Array vs Linked List arrays Easier to use and access Faster access to the elements Fixed size One block allocation Complex position-based insertion 자바프로그래밍 Linked Lists Flexibility - insert (or delete) in contant time No single allocation of memory needed Dynamic allocation Complex to use and access No constant time access to the elements 강원대학교 4/79 LinkedList Methods 자바프로그래밍 강원대학교 5/79 A List Iterator LinkedList<String> staff = new LinkedList<String>(); staff.addLast("Diana"); staff.addLast("Harry"); staff.addLast("Romeo"); staff.addLast("Tom"); ListIterator<String> iterator = staff.listIterator(); iterator.next(); // D|HRT iterator.next(); // DH|RT java api 자바프로그래밍 강원대학교 6/79 A List Iterator 자바프로그래밍 강원대학교 7/79 List Iterator while iterator.hasNext() { String name = iterator.next(); Do something with name } 자바프로그래밍 강원대학교 8/79 Adding to List (using the List Iterator) iterator.add("Juliet"); 자바프로그래밍 강원대학교 9/79 List Iterator • LinkedList is a doubly linked list Class stores two links: o One to the next element, and o One to the previous element • To move the list position backwards, use: hasPrevious previous 자바프로그래밍 강원대학교 10/79 Removing from LinkedList (using the ListIterator) • The remove method Removes and returns the object that was returned by the last call to next or previous while (iterator.hasNext()) { String name = iterator.next(); iterator.remove(); } 자바프로그래밍 강원대학교 11/79 Adding and Removing from a LinkedList • Be careful when calling remove: It can be called only once after calling next or previous: iterator.next(); iterator.next(); iterator.remove(); iterator.remove(); // Error: You cannot call remove twice. You cannot call it immediately after a call to add: iter.add("Fred"); iter.remove(); // Error: Can only call remove after // calling next or previous 자바프로그래밍 강원대학교 12/79 Methods of the ListIterator Interface 자바프로그래밍 강원대학교 13/79 ListTester.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.LinkedList; import java.util.ListIterator; /** A program that tests the LinkedList class */ public class ListTester { public static void main(String[] args) { LinkedList<String> staff = new LinkedList<String>(); staff.addLast("Diana"); staff.addLast("Harry"); staff.addLast("Romeo"); staff.addLast("Tom"); // | in the comments indicates the iterator position ListIterator<String> iterator = staff.listIterator(); // |DHRT iterator.next(); // D|HRT iterator.next(); // DH|RT Continued 자바프로그래밍 강원대학교 14/79 ListTester.java (cont.) 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // Add more elements after second element iterator.add("Juliet"); // DHJ|RT iterator.add("Nina"); // DHJN|RT iterator.next(); // DHJNR|T // Remove last traversed element iterator.remove(); // DHJN|T // Print all elements for (String name : staff) System.out.print(name + " "); System.out.println(); System.out.println("Expected: Diana Harry Juliet Nina Tom"); } } Continued 자바프로그래밍 강원대학교 15/79 ArrayList vs LinkedList java api Arraylist uses an array for internal storage 자바프로그래밍 강원대학교 16/79 Self Check Do linked lists take more storage space than arrays of the same size? Answer: Yes, for two reasons. You need to store the node references, and each node is a separate object. (There is a fixed overhead to store each object in the virtual machine.) 자바프로그래밍 강원대학교 17/79 Self Check Why don’t we need iterators with arrays? Answer: An integer index can be used to access any array location. 자바프로그래밍 강원대학교 18/79 Core Collections Framework Collection Set SortedSet List Map Queue SortedMap 이들은 모두 인터페이스이다. Set: cannot take any duplicate elements. List: ordered, allows duplicate elements Queue: FIFO (First In First Out) Map: Collection of key and value pairs. does not allow duplicate keys. Sorted Set: Ordered version of the set interface. Sorted Map: Maintains ascending order of keys. 자바프로그래밍 강원대학교 19/79 Set 자바프로그래밍 강원대학교 20/79 Sets • Collection of distinct elements • Elements can be added and removed 자바프로그래밍 강원대학교 21/79 Fundamental Operations on a Set • Adding an element Adding an element has no effect if the element is already in the set • Removing an element Attempting to remove an element that isn’t in the set is silently ignored • Containment testing (Does the set contain a given object?) • Listing all elements (in arbitrary order) 자바프로그래밍 강원대학교 22/79 Sets • We could use a linked list to implement a set Removing, and containment testing would be relatively slow • There are data structures that can handle these operations much more quickly Hash tables Trees 자바프로그래밍 강원대학교 23/79 Sets • Standard Java library provides set implementations based on both data structures HashSet TreeSet • Both of these data structures implement the Set interface • As a rule of thumb, use a hash set unless you want to visit the set elements in sorted order 자바프로그래밍 강원대학교 24/79 Set Classes and Interface in the Standard Library 자바프로그래밍 강원대학교 25/79 Using a Set • Example: Using a set of strings • Construct the Set: Set<String> names = new HashSet<String>(); or Set<String> names = new TreeSet<String>(); • Add and remove elements: names.add("Romeo"); names.remove("Juliet"); • Test whether an element is contained in the set: if (names.contains("Juliet")) . . . 자바프로그래밍 강원대학교 26/79 Iterator • Use an iterator to visit all elements in a set • A set iterator does not visit the elements in the order in which they were inserted 자바프로그래밍 강원대학교 27/79 Visiting All Elements with an Iterator Iterator<String> iter = names.iterator(); while (iter.hasNext()) { String name = iter.next(); Do something with name } or, using the “for each” loop: for (String name : names) { Do something with name } 자바프로그래밍 강원대학교 28/79 Iterator • An element cannot be added to a set at an iterator position List<E>는 아래 두 메소드를 지원함 ListIterator<E> listIterator() Iterator<E> iterator() Set<E>는 아래 메소드만을 지원함 Iterator<E> iterator() Interator<E> boolean E void 자바프로그래밍 hasNext() next() remove() ListIterator<E> voidadd(E e) boolean hasNext() boolean hasPrevious() E next() int nextIndex() E previous() int previousIndex() void remove() void set(E e) 강원대학교 29/79 Set Test Program 1. Read in all words from a dictionary file that contains correctly spelled words and place them into a set 2. Read all words from a document into a second set — here, the book “Alice in Wonderland” 3. Print all words from that set that are not in the dictionary set — potential misspellings 자바프로그래밍 강원대학교 30/79 SpellCheck.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import import import import import java.util.HashSet; java.util.Scanner; java.util.Set; java.io.File; java.io.FileNotFoundException; /** This program checks which words in a file are not present in a dictionary. */ public class SpellCheck { public static void main(String[] args) throws FileNotFoundException { Continued 자바프로그래밍 강원대학교 31/79 SpellCheck.java (cont.) 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // Read the dictionary and the document Set<String> dictionaryWords = readWords("words"); Set<String> documentWords = readWords("alice30.txt"); // Print all words that are in the document but not the dictionary for (String word : documentWords) { if (!dictionaryWords.contains(word)) { System.out.println(word); } } } Continued 자바프로그래밍 강원대학교 32/79 SpellCheck.java (cont.) 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 /** Reads all words from a file. @param filename the name of the file @return a set with all lowercased words in the file. Here, a word is a sequence of upper- and lowercase letters. */ public static Set<String> readWords(String filename) throws FileNotFoundException { Set<String> words = new HashSet<String>(); Scanner in = new Scanner(new File(filename)); // Use any characters other than a-z or A-Z as delimiters in.useDelimiter("[^a-zA-Z]+"); while (in.hasNext()) { words.add(in.next().toLowerCase()); } return words; } } 자바프로그래밍 강원대학교 33/79 SpellCheck.java Program Run: neighbouring croqueted pennyworth dutchess comfits xii dinn clamour ... 자바프로그래밍 강원대학교 34/79 Self Check Arrays and lists remember the order in which you added elements; sets do not. Why would you want to use a set instead of an array or list? Answer: Efficient set implementations can quickly test whether a given element is a member of the set. 자바프로그래밍 강원대학교 35/79 Self Check Why are set iterators different from list iterators? Answer: Sets do not have an ordering, so it doesn’t make sense to add an element at a particular iterator position, or to traverse a set backwards. 자바프로그래밍 강원대학교 36/79 Self Check Suppose you changed line 18 of the SpellCheck program to use a TreeSet instead of a HashSet. How would the output change? Answer: The words would be listed in sorted order. 자바프로그래밍 강원대학교 37/79 Self Check When would you choose a tree set over a hash set? Answer: When it is desirable to visit the set elements in sorted order. 자바프로그래밍 강원대학교 38/79 Map 자바프로그래밍 강원대학교 39/79 Maps • A map keeps associations between key and value objects • Every key in a map is unique • A value may be associated with several keys 자바프로그래밍 강원대학교 40/79 Maps • Classes that implement the Map interface HashMap TreeMap • As a rule of thumb, use a hash set unless you want to visit the set elements in sorted order 자바프로그래밍 강원대학교 41/79 Map Classes and Interfaces 자바프로그래밍 강원대학교 42/79 Using a Map • Example: Associate names with colors • Construct the Map: Map<String, Color> favoriteColors = new HashMap<String, Color>(); or Map<String, Color> favoriteColors = new TreeMap<String, Color>(); • Add an association: favoriteColors.put("Juliet", Color.RED); • Change an existing association: favoriteColors.put("Juliet",Color.BLUE); 자바프로그래밍 강원대학교 43/79 Using a Map • Get the value associated with a key: Color julietsFavoriteColor = favoriteColors.get("Juliet”); • Remove a key and its associated value: favoriteColors.remove("Juliet"); 자바프로그래밍 강원대학교 44/79 Printing Key/Value Pairs Set<String> keySet = m.keySet(); for (String key : keySet) { Color value = m.get(key); System.out.println(key + ” : " + value); } 자바프로그래밍 강원대학교 45/79 MapDemo.java 1 import java.awt.Color; 2 import java.util.HashMap; 3 import java.util.Map; 4 import java.util.Set; 5 6 /** 7 This program demonstrates a map that maps names to colors. 8 */ 9 public class MapDemo 10 { 11 public static void main(String[] args) 12 { 13 Map<String, Color> favoriteColors = new HashMap<String, Color>(); 14 favoriteColors.put("Juliet", Color.BLUE); 15 favoriteColors.put("Romeo", Color.GREEN); 16 favoriteColors.put("Adam", Color.RED); 17 favoriteColors.put("Eve", Color.BLUE); 18 Continued 자바프로그래밍 강원대학교 46/79 MapDemo.java (cont.) 19 20 21 22 23 24 25 26 27 28 // Print all keys and values in the map Set<String> keySet = favoriteColors.keySet(); for (String key : keySet) { Color value = favoriteColors.get(key); System.out.println(key + " : " + value); } } } Program Run: Romeo : java.awt.Color[r=0,g=255,b=0] Eve : java.awt.Color[r=0,g=0,b=255] Adam : java.awt.Color[r=255,g=0,b=0] Juliet : java.awt.Color[r=0,g=0,b=255] 자바프로그래밍 강원대학교 47/79 Self Check What is the difference between a set and a map? Answer: A set stores elements. A map stores associations between keys and values. 자바프로그래밍 강원대학교 48/79 Self Check Why is the collection of the keys of a map a set? Answer: The ordering does not matter, and you cannot have duplicates. 자바프로그래밍 강원대학교 49/79 Core Collections Framework Collection Set List Map Queue SortedMap SortedSet Set: cannot take any duplicate elements. List: ordered, allows duplicate elements Queue: FIFO (First In First Out) Map: Collection of key and value pairs. does not allow duplicate keys. Sorted Set: Ordered version of the set interface. Sorted Map: Maintains ascending order of keys. 자바프로그래밍 강원대학교 50/79 Operations Supported by Collection <E> interface boolean isEmpty(); boolean contains (Object element); boolean add (Object element); boolean remove (Object element); Iterator <E> iterator(); boolean containsAll (Collection <?> C); boolean addAll (Collection <? extends E> C); boolean removeAll (Collection() <?> C); boolean retainAll (Collection <?> C); void clear(); Object[ ] toArray(); <T> T[ ] toArray(T[ ]a); 51/79 Iteration • Two ways to iterate over Collections: – Iterator static void loopThrough(Collection col){ for (Iterator <E> iter = col.iterator(); iter.hasnext()) { Object obj=iter.next(); } } – For-each static void loopThrough(Collection col){ for (Object obj: col) { //access object } } 자바프로그래밍 강원대학교 52/79 자바프로그래밍 강원대학교 53/79 HashTable과 SortedTree 구현 자바프로그래밍 강원대학교 54/79 Hash Tables • Hashing can be used to find elements in a data structure quickly without making a linear search • A hash table can be used to implement sets and maps • A hash function computes an integer value (called the hash code) from an object • A good hash function minimizes collisions — identical hash codes for different objects • To compute the hash code of object x: int h = x.hashCode(); 자바프로그래밍 강원대학교 55/79 Sample Strings and Their Hash Codes 자바프로그래밍 String Hash Code "Adam" 2035631 "Eve" 700068 "Harry" 69496448 "Jim" 74478 "Joe" 74656 "Juliet" -2065036585 "Katherine" 2079199209 "Sue" 83491 강원대학교 56/79 Hash Table with Buckets to Store Elements with Same Hash Code 자바프로그래밍 강원대학교 57/79 Binary Search Trees • Data In order • Fast insertion and removal of elements • Fast searching • A binary tree consists of two nodes, each of which has two child nodes • All nodes in a binary search tree fulfill the property that: Descendants to the left have smaller data values than the node data value Descendants to the right have larger data values than the node data value 자바프로그래밍 강원대학교 58/79 A Binary Search Tree 자바프로그래밍 강원대학교 Big Java by Cay Horstmann Copyright © 2009 by John Wiley & Sons.59/79 All rights Generics 자바프로그래밍 강원대학교 60/79 List myList = new LinkedList(); // myList에는 무엇이든 넣을 수 있다. // myList에 Integer 객체만을 넣기로 작정함 myList.add(new Integer(0)); Why generics? Integer x = (Integer) myList.get(0); // 0번째 항목 반환 // LinkedList의 get 메소드가 반환하는 것은 Object 타입이므로 // Integer 타입으로 캐스팅, 캐스팅 하지 않는 경우 컴파일 오류 발생! // 프로그래머 실수로 // myList에 Integer 객체가 아닌 것을 넣으면 런타임 에러 발생! 견고한 (robust) 프로그램 List<Integer> myList = new LinkedList<Integer>(); // myList에는 Integer 객체만 넣을 수 있다. myList.add(new Integer(0)); Integer x = myList.get(0); // get(0)가 반환하는 것은 Integer 타입, 캐스팅 불필요! 자바프로그래밍 강원대학교 61/79 Type parameter, type argument public interface List <E>{ void add(E e); E get(int index); ••• } type parameter List<Integer> List<Double> type argument • • Gereric type 클래스나 인터페이스는 한 번 컴파일되어 하나의 바이트코드 파일로 존재 실행시 (메소드가 호출될 때) type argument 가 type parameter에 대입됨 자바프로그래밍 강원대학교 62/79 Java.util.List<E>, java.util.Iterator<E> public interface List <E>{ void add(E e); E get(int index); Iterator<E> iterator(); } public interface Iterator<E>{ E next(); boolean hasNext(); } List<Integer> myList = new LinkedList<Integer>(); myList.add(new Integer(0)); myList.add(new Integer(1)); Iterator<Integer> it = myList.iterator(); while(it.hasNext()) System.out.println(it.next()); 자바프로그래밍 강원대학교 63/79 Java.util.List<E>, java.util.Iterator<E> public interface List <E>{ void add(E e); E get(int index); Iterator<E> iterator(); } public interface Iterator<E>{ E next(); boolean hasNext(); } List<Double> myList = new LinkedList<Double>(); myList.add(new Double(0.0)); myList.add(new Double(1.0)); Iterator<Double> it = myList.iterator(); while(it.hasNext()) System.out.println(it.next()); 자바프로그래밍 강원대학교 64/79 Generics and Subtyping • String은 Object이다. (String은 Object의 서브타입) • List<String>은 List<Object>이다? No! (List<String>은 List<Object>의 서브타입이 아님) 만약, List<String>이 List<Object>의 서브타입이라면, List<String> ls = new ArrayList<String>(); List<Object> lo = ls; // aliasing lo.add(new Object()); String s = ls.get(0); // Generics의 타입 체크 기능 무력화! 자바프로그래밍 강원대학교 65/79 Wildcards void printCollection(Collection<Object> c) { for (Object e : c) { System.out.println(e); } } Collection<String> c = new ArrayList<String>(); c.add("aa"); c.add("bb"); printCollection(c); // error! // Collection<String>은 Collection<Object>의 서브타입이 아니므로 void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e); } } // Collection of unknowns Collection <String> c = new ArrayList<String>(); c.add("aa"); c.add("bb"); printCollection(c); // OK! 자바프로그래밍 강원대학교 66/79 Wildcards Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error c의 원소의 타입이 unknown인 경우 c에 어떤 것도 add할 수 없다! (null은 넣을 수 있다) Object o = c.iterator().next(); 자바프로그래밍 // OK! 강원대학교 67/79 Bounded Wildcards public abstract class Shape { public abstract void draw(Canvas c); } public class Circle extends Shape { private int x, y, radius; public void draw(Canvas c) { ... } } public class Rectangle extends Shape { private int x, y, width, height; public void draw(Canvas c) { ... } } 자바프로그래밍 public void drawAll(List<Shape> shapes) { for (Shape s: shapes) { s.draw(this); } } List<Shape> ls = new List<Shape>(); drawAll(ls); // OK! List<Circle> lc = new List<Circle>(); drawAll(lc); // Compile Error! List<Rectangle> lr = new List<Rectangle>(); drawAll(lr); // Compile Error! 강원대학교 68/79 Bounded Wildcards public abstract class Shape { public abstract void draw(Canvas c); } public class Circle extends Shape { private int x, y, radius; public void draw(Canvas c) { ... } } public class Rectangle extends Shape { private int x, y, width, height; public void draw(Canvas c) { ... } } 자바프로그래밍 unknown type, bounded wildcard public void drawAll(List<? extends Shape> shapes){ for (Shape s: shapes) { s.draw(this); } } List<Shape> ls = new List<Shape>(); drawAll(ls); // OK! List<Circle> lc = new List<Circle>(); drawAll(lc); // OK! List<Rectangle> lr = new List<Rectangle>(); drawAll(lr); // OK! 강원대학교 69/79 Bounded Wildcards ? - Unknown type! public void drawAll(List<? extends Shape> shapes){ shapes.add(0, new Rectangle()); // Compile-time error! } 자바프로그래밍 강원대학교 70/79 Arrays vs Generics String[] strings = new String[] { "a", "b" }; Object[] objects = strings; // OK! objects[0] = new Date(); // <-- Runtime error here List<String> ls = new LinkedList<String>(); List<Object> lo = ls; // Compile error 자바프로그래밍 강원대학교 71/79 Generic Methods class Collections { static void fromArrayToCollection(Object[] a, Collection<Object> c) { for (Object o : a) c.add(o); } } public class GenericMethods { public static void main(String[] args){ String[] sa = {"aa", "bb"}; Collection<Object> co = new ArrayList<Object>(); Collections.fromArrayToCollection(sa, co); for (Object o : co) System.out.println(o); String array는 Object array에 대입 가능 } } String array를 collection of object 에 넣음! 자바프로그래밍 강원대학교 72/79 Generic Methods String array는 Collection of String에, Circle array는 Collection of Circle에 넣고 싶다면? class Collections { static void fromArrayToCollection(Object[] a, Collection<?> c) { for (Object o : a) c.add(o); // 컴파일 에러! unknown type } } 자바프로그래밍 강원대학교 73/79 Generic Methods String array는 Collection of String에, Circle array는 Collection of Circle에 넣고 싶다면? static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); // Correct } } 자바프로그래밍 강원대학교 74/79 static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) c.add(o); } Object[] oa = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromArrayToCollection(oa, co); // T inferred to be Object String[] sa = new String[100]; Collection<String> cs = new ArrayList<String>(); fromArrayToCollection(sa, cs); // T inferred to be String fromArrayToCollection(sa, co); 자바프로그래밍 // T inferred to be Object 강원대학교 75/79 static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) c.add(o); } Number은 BigInteger, Byte, Double, Float, Integer, Long, Short의 super class! Integer[] ia = new Integer[100]; Float[] fa = new Float[100]; Number[] na = new Number[100]; Collection<Number> cn = new ArrayList<Number>(); fromArrayToCollection(ia, cn); fromArrayToCollection(fa, cn); fromArrayToCollection(na, cn); fromArrayToCollection(na, co); // // // // fromArrayToCollection(na, cs); // compile-time error 자바프로그래밍 T T T T inferred inferred inferred inferred 강원대학교 to to to to be be be be Number Number Number Object 76/79 Generic Methods class Collections { public static <T> void copy(List<T> dest, List<? extends T> src) { ... } 자바프로그래밍 강원대학교 77/79 참고자료 • http://docs.oracle.com/javase/tutorial/extra/g enerics/index.html 자바프로그래밍 강원대학교 78/79 자바프로그래밍 강원대학교 79/79