Java Schulung Objektorientierte Programmierung in Java Teil V: Die Java Collection Klassen Prof. Dr. Nikolaus Wulff Collections in Java 2 Java 2 Collections: http://java.sun.com/products/jdk/1.2/docs/guide/collections/index.html [Offizielle Dokumentationen zum Thema Collections in Java 2] Java 2 Collections Tutorial Online: http://java.sun.com/docs/books/tutorial/collections/index.html [Einführung in die Verwendung der Collection-Klassen in Java 2] David Flanagan: Java in a Nutshell. 2nd Edition, O‘Reilly, 1997, ISBN 1-56592-262-x. [Der Java-Nachschlage-Klassiker. Kurz und knapp durch die wesentlichen Java-Bestandteile und -Packages.] Prof. Dr. Nikolaus Wulff 2 java.util.Collection • Eine Collection ist ein Objekt, das eine Gruppe von anderen Objekten zusammenfaßt. • Collections werden verwendet um andere Objekte zu speichern, zu manipulieren und Mengen von Objekten von einer Operation an eine andere weiterzugeben. • Collections enthalten i.d.R. Objekte vom selben Typ: eine Menge von Briefen, eine Menge von Telefonnummern mit Namen etc. • Prof. Dr. Nikolaus Wulff Items • • Collection • • .... 3 Fachliche und technische Behälter Sparbuch _saldo gibSaldo _kontobewegungen gibAnzahl • gibBewegungenVom(12.1.2000) • Items • • • • .... Collection Prof. Dr. Nikolaus Wulff • Fachliche Behälter implementieren ein Konzept der Anwendungsgebiets. Es sind Gegenstände, die der Anwender bei seiner Arbeit einsetzt und für die sich ein typischer Umgang etabliert hat. • Technische Behälter werden als interne Repräsentation fachlicher Behälter verwendet. • Fachliche Behälter stehen daher zu technischen Behältern in einer Benutzt-Beziehung. • Technische Behälter sollten wie fachliche Behälter nach ihrem Umgang modelliert und klassifiziert werden. • Für technische Behälter haben sich typische informatische Arten des Umgang herausgebildet (Stack, Queue, List, Set, Map). 4 Collections in Java 2 Collection ist die Wurzel der Collection-Hierarchie. Für Collection gibt es keine Implementation. Dieses Interface wird verwendet, wenn eine Menge von Objekten so generell wie möglich verwendet werden soll. Ein Set ist eine Menge, die keine Duplikate enthalten kann. In einem SortedSet sind die Objekt in aufsteigender Reihenfolge sortiert enthalten. Prof. Dr. Nikolaus Wulff Eine Map ist ein Objekt, das Schlüssel und Werte Paar enthält. Jeder Schlüssel kann nur einmal vorkommen. In einer SortedMap sind die Objekt in aufsteigender Reihenfolge der Schlüssel sortiert. Eine List enthält ihre Objekte in einer geordneten Reihenfolge, die vom Benutzer der Liste festgelegt wird. Duplikate sind möglich. Listenelemente können über einen Index angesprochen werden. Package java.util 5 Implementationsvarianten • Für Set, List und Map gibt es jeweils zwei Implementationsvarianten. Die zwei Variante zum selben Interface haben jeweils spezifische Vor- und Nachteile und sollten je nach Verwendungszusammenhang ausgewählt werden. • Für SortedSet und SortedMap existiert jeweils nur eine Implementation, nämlich TreeSet und TreeMap. Hash Table Set List Map Resizable Array HashSet Balanced Tree TreeSet ArrayList HashMap Linked List LinkedList TreeMap List l1 = new ArrayList(); List l2 = new LinkedList(); Map m1 = new HashMap(); Prof. Dr. Nikolaus Wulff 6 Das Interface Collection public interface Collection { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(Object element); boolean remove(Object element); Iterator iterator(); // Bulk Operations boolean containsAll(Collection c); boolean addAll(Collection c); boolean removeAll(Collection c); boolean retainAll(Collection c); void clear(); // Array Operations Object[] toArray(); Object[] toArray(Object a[]); } Prof. Dr. Nikolaus Wulff 7 Das Interface Map public interface Map { // Basic Operations int size(); boolean isEmpty(); boolean containsKey(Object key); boolean containsValue(Object value); Object put(Object key, Object element); Object get(Object get); Object remove(Object key); Set keySet(); Collection values(); // Bulk Operations void putAll(Map map); void clear(); } Prof. Dr. Nikolaus Wulff 8 Der Iterator public interface Iterator { boolean hasNext(); Object next(); void remove(); // Optional } Collection c = new LinkedList(); ... Konto k; Iterator i = c.iterator(); while (i.hasNext()) { k = (Konto)i.next(); if (k.gibSaldo < 100000) i.remove(); } Prof. Dr. Nikolaus Wulff Ein Iterator-Objekt erlaubt es, den Inhalt einer Collection zu durchlaufen und auch Elemente zu löschen. Polymorphie Das Durchlaufen einer Collection kann auf jedem Objekt ausgeführt werden, dessen Klasse von Collection erbt. Egal welche Implementationsvariante vorliegt. Voraussetzung ist, daß das Löschen von Elementen in der verwendeten Variante unterstützt wird. 9 Enumeration • Die Collection Klassen wurden mit dem JDK1.2 generell überarbeitet und erweitert. • Die alten Collections (Vector, Hashtable) verwenden statt des Iterators eine Enumeration. Diese macht im Prinzip das selbe nur mit einer etwas anderen Syntax: Vector v = new Vector(); ... Enumeration e = v.elements(); while (e.hasMoreElements()) { Object o = e.nextElement() ... } Prof. Dr. Nikolaus Wulff Collection c = new ArrayList(); ... Iterator i = c.iterator(); while (i.hasNext()) { Object o = i.next(); ... } 10 Array-Operationen • Mit den Collection.toArray-Operationen kann der Inhalt einer Collection in einen Array überführt werden. • Mit Arrays.asList können Arrays in Listen konvertiert werden. public interface Collection { Object[] toArray(); } Ein neues Array-Objekt wird erzeugt und mit den Elementen der Collection gefüllt. Collection c = new LinkedList(); Object[] a = c.toArray(); public interface Collection { Object[] toArray(Object a[]); } Ein neues Array-Objekt wird erzeugt und mit den Elementen der Collection gefüllt. Wenn die Länge 0 ist, wird ein neues Array mit dem angegebenen Typ mit ausreichender Größe erzeugt. Collection c = new LinkedList(); String[] a = (String[]) c.toArray(new String[0]); Prof. Dr. Nikolaus Wulff 11 Java Generics • Seit dem JDK1.5 enthält Java Generics/Templates. • Diese beinhalten insbesondere typesichere Collections und Maps. • Templates werden mit einem „Platzhalter“ <T> für den generischen Typen T definiert. • Verwendet werden sie dann zur Compilezeit mit einem explizit angegeben Typen. • Beispiel: ArrayList<T>, Collectiont<T>, Iteratort<T> ArrayList<Money>, Collection<Money>, Iterator<Money>... Prof. Dr. Nikolaus Wulff 12 Collection ohne Generics • Ohne Generics müssen Iterator und Collections immer auf den passenden Typ gecasted werden: Collection saldo = new ArrayList(); public void addMoney(Money m) { saldo.add(m); } public void printMoney() { Iterator moneyIterator = saldo.iterator(); while(moneyIterator.hasNext()) { Money m = (Money) moneyIterator.next(); print(m); } } Prof. Dr. Nikolaus Wulff 13 Collection mit Generics • Mit Generics entfällt das Casten, die Collection akzeptiert nur den „richtigen Typ“ und liefert diesen auch ohne Cast zurück: Collection<Money> saldo = new ArrayList<Money>(); public void addMoney(Money m) { saldo.add(m); } public void printMoney() { Iterator<Money> moneyIterator = saldo.iterator(); while(moneyIterator.hasNext()) { Money m = moneyIterator.next(); print(m); Kein Cast mehr } } Nikolaus Wulff Prof. Dr. 14 For-each Schleife • Zusätzlich zu den Generics ist es möglich vereinfachte for-each Schleifen zu schreiben. Statt: Iterator<Money> moneyIterator = saldo.iterator(); while(moneyIterator.hasNext()) { Money m = moneyIterator.next(); print(m); } Jetzt: for(Money m : saldo) { print(m); } Prof. Dr. Nikolaus Wulff 15 Übung Server Client <<uses>> addService(service : Service) : void getService(name : String) : Service ServerException throws name : String service 0..1 <<Interface>> Service doTask(req : Request, res : Response) : void getName() : String • Wir implementieren einen Server, der beliebige Services zur Verfügung stellt. • Diese Services lassen sich hinzufügen und per Namen referenzieren mit den Operationen addService und getService Prof. Dr. Nikolaus Wulff 16 Hinweis • Wir wissen so gut wie nichts über die angebotenen Dienste (Services), das irritiert zunächst... • Für die gestellte Aufgabe des Servers (Verwalten von Services) spielt dies jedoch keine Rolle! • Mit welcher Collection Klasse werden die Services am besten verwaltet? • Um die Funktionalität unseres Servers zu über-prüfen verwenden wir einen JUnit Test als Client. • Frage: Was muss getestet werden, wo bekommen wir einen Service her? Prof. Dr. Nikolaus Wulff 17 Hinweis: Klassendiagramm TestCase (from j unit.framew ork) ServerTest Server server testAddService() testGetService() 1 addService() getService() name : String <<inner class>> 1 DummyService • • service 0..1 <<Int erface>> Service DummyService ist ein JUnit Mock Objekt, das die Service Schnittstelle implementiert. Wir verwenden eine innere Klasse, da sie nur innerhalb des Kontext des Tests Sinn macht. Prof. Dr. Nikolaus Wulff 18