13주 컬렉션 (Collection) 제네릭스 (Generics) 자바프로그래밍 강원대학교 1 Collections - 많은 데이터를 저장하는 방법 배열과 ArrayList 외에도 많은 클래스가 있다. 이들의 특징과 용도를 알아본다. 자바프로그래밍 강원대학교 2 LinkedList 먼저 구체적 예를 하나 살펴보자 자바프로그래밍 강원대학교 3 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 Arraylist uses an array for internal storage 자바프로그래밍 강원대학교 4 LinkedList Methods 자바프로그래밍 강원대학교 5 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 자바프로그래밍 강원대학교 6 A List Iterator 자바프로그래밍 강원대학교 7 List Iterator iterator.next(); if (iterator.hasNext()) iterator.next(); while iterator.hasNext() { String name = iterator.next(); Do something with name } 자바프로그래밍 강원대학교 8 Adding and Removing from a LinkedList • The add method: Adds an object after the iterator Moves the iterator position past the new element: iterator.add("Juliet"); 자바프로그래밍 강원대학교 9 A Conceptual View of the List Iterator 자바프로그래밍 강원대학교 10 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 자바프로그래밍 강원대학교 11 Adding and Removing from a LinkedList • The remove method Removes and Returns the object that was returned by the last call to next or previous //Remove all names that fulfill a certain condition while (iterator.hasNext()) { String name = iterator.next(); if (name fulfills condition) iterator.remove(); } 자바프로그래밍 강원대학교 12 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 자바프로그래밍 강원대학교 13 Methods of the ListIterator Interface 자바프로그래밍 강원대학교 14 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 자바프로그래밍 강원대학교 15 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 자바프로그래밍 강원대학교 16 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 Self Check Why don’t we need iterators with arrays? Answer: An integer index can be used to access any array location. 자바프로그래밍 강원대학교 18 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 Set 자바프로그래밍 강원대학교 20 Sets • Set: Unordered collection of distinct elements • Elements can be added, located, and removed • Sets don’t have duplicates 자바프로그래밍 강원대학교 21 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 Sets • We could use a linked list to implement a set Adding, removing, and containment testing would be relatively slow • There are data structures that can handle these operations much more quickly Hash tables Trees 자바프로그래밍 강원대학교 23 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 Set Classes and Interface in the Standard Library 자바프로그래밍 강원대학교 25 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 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 • An element cannot be added to a set at an iterator position 자바프로그래밍 강원대학교 27 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 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 자바프로그래밍 강원대학교 29 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 자바프로그래밍 강원대학교 30 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 자바프로그래밍 강원대학교 31 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; } } Continued 자바프로그래밍 강원대학교 32 SpellCheck.java (cont.) Program Run: neighbouring croqueted pennyworth dutchess comfits xii dinn clamour ... 자바프로그래밍 강원대학교 33 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. 자바프로그래밍 강원대학교 34 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. 자바프로그래밍 강원대학교 35 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. 자바프로그래밍 강원대학교 36 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. 자바프로그래밍 강원대학교 37 Map 자바프로그래밍 강원대학교 38 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 • Classes that implement the Map interface HashMap TreeMap • Both of these data structures implement the Map interface • As a rule of thumb, use a hash set unless you want to visit the set elements in sorted order 자바프로그래밍 강원대학교 39 An Example of a Map 자바프로그래밍 강원대학교 40 Map Classes and Interfaces 자바프로그래밍 강원대학교 41 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); 자바프로그래밍 강원대학교 42 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"); 자바프로그래밍 강원대학교 43 Printing Key/Value Pairs Set<String> keySet = m.keySet(); for (String key : keySet) { Color value = m.get(key); System.out.println(key + ” : " + value); } 자바프로그래밍 강원대학교 44 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 자바프로그래밍 강원대학교 45 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] Continued 자바프로그래밍 강원대학교 46 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. 자바프로그래밍 강원대학교 47 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. 자바프로그래밍 강원대학교 48 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. 자바프로그래밍 강원대학교 49 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); 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 } } 자바프로그래밍 강원대학교 51 자바프로그래밍 강원대학교 52 HashTable과 SortedTree 구현 자바프로그래밍 강원대학교 53 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(); 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 Hash Table with Buckets to Store Elements with Same Hash Code Binary Search Trees • Fast insertion and removal of elements • Fast searching • Data In order • 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 A Binary Search Tree Big Java by Cay Horstmann Copyright © 2009 by John Wiley & Sons. All rights Generics 자바프로그래밍 강원대학교 59 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 타입, 캐스팅 불필요! 자바프로그래밍 강원대학교 60 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에 대입됨 자바프로그래밍 강원대학교 61 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()); 자바프로그래밍 강원대학교 62 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()); 자바프로그래밍 강원대학교 63 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의 타입 체크 기능 무력화! 자바프로그래밍 강원대학교 64 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! 자바프로그래밍 강원대학교 65 Wildcards Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error c의 원소의 타입이 unknown이므로 c에 어떤 것도 add할 수 없다! (null은 넣을 수 있다) Object o = c.iterator().next(); 자바프로그래밍 // OK! 강원대학교 66 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! 강원대학교 67 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<? extends Shape> shapes){ for (Shape s: shapes) { unknown type, s.draw(this); bounded wildcard } } 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! 강원대학교 68 Bounded Wildcards ? - Unknown type! public void drawAll(List<? extends Shape> shapes){ shapes.add(0, new Rectangle()); // Compile-time error! } 자바프로그래밍 강원대학교 69 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를 object collection에 넣음! 자바프로그래밍 강원대학교 70 Generic Methods String array일 때는 String의 Collection에, Circle array 일때 는 Circle Collection에 넣고 싶다면? class Collections { static void fromArrayToCollection(Object[] a, Collection<?> c) { for (Object o : a) c.add(o); // 컴파일 에러! known type } } 자바프로그래밍 강원대학교 71 Generic Methods String array일 때는 String의 Collection에, Circle array 일때 는 Circle Collection에 넣고 싶다면? static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); // Correct } } 자바프로그래밍 강원대학교 72 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 자바프로그래밍 강원대학교 73 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 74 Generic Methods class Collections { public static <T> void copy(List<T> dest, List<? extends T> src) { ... } 자바프로그래밍 강원대학교 75 참고자료 • http://docs.oracle.com/javase/tutorial/extra/g enerics/index.html 자바프로그래밍 강원대학교 76