Collections

Werbung
Wo sind wir?
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Java-Umgebung
Lexikale Konventionen
Datentypen
Kontrollstrukturen
Ausdrücke
Klassen, Pakete, Schnittstellen
JVM
Exceptions
Java Klassenbibliotheken
Ein-/Ausgabe
Collections
Threads
Applets, Sicherheit
Grafik
Beans
Integrierte Entwicklungsumgebungen
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
338
Container
Container sind Behälter, die andere Dinge speichern können.
Schon bekannte Beispiele aus der Einführungsvorlesung sind:
•
Liste
•
Stack
•
Schlange
•
Baum
Typische Operationen auf einem Container sind z.B.:
•
Füge ein Element zu dem Container hinzu
•
Lösche ein Objekt aus dem Container
•
Suche ein bestimmtes Objekt im Container
•
Enthält der Container Elemente (nicht leer)?
•
Wende eine Operation auf alle Container-Elemente an
Man kann sich Container mit unterschiedlichen Eigenschaften vorstellen:
•
Ein Element darf höchstens ein mal vorkommen (keine Duplikate)
•
Die Anzahl der Elemente im Container bleibt überwiegend konstant
(→Effizienzfrage)
•
Spezielle Abspeicherungstechniken zur Optimierung von häufig
benutzten Operationen (→ Vorlesung "Algorithmen und Datenstrukturen")
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
339
Collection Framework
Java kennt das Collection Framework (im Paket java.util; siehe APIDokumentation), in dem Container mit unterschiedlichen Eigenschaften zur
Verfügung gestellt werden. Es werden folgende Arten von Collections
unterschieden, die jeweils gewisse Eigenschaften haben und ausnutzen:
1.
2.
3.
Listen (List; geordnete Menge, d.h. es gibt ein i-tes Element)
Mengen (Set; keine Duplikate)
Abbildungen (Map; Schlüssel-Wert-Paare)
In den drei Kategorien, die als Schnittstellen in Java definiert sind und die die
Schnittstelle Collection erweitern, gibt es Klassen, die diese Schnittstellen
in einer bestimmten Weise implementieren. Z.B. lässt sich eine Liste durch
eine einfach verkettete Liste implementieren, durch eine doppelt verkettete
Liste, durch ein dynamisch wachsendes Feld usw.
Zum Collection Framework gehören weiterhin Algorithmen, wie z.B. Sortieren
einer Liste, (binäres) Suchen in einer Liste usw.
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
340
Collection-Schnittstelle
Jeder Container muss die Schnittstelle Collection implementieren.
public interface Collection {
// Basic Operations
int size();
boolean isEmpty();
boolean contains(Object element);
boolean add(Object element);
// Optional
boolean remove(Object element);
// Optional
Iterator iterator();
// Bulk Operations
boolean containsAll(Collection c);
boolean addAll(Collection c);
//
boolean removeAll(Collection c); //
boolean retainAll(Collection c); //
void clear();
//
Optional
Optional
Optional
Optional
// Array Operations
Object[] toArray();
Object[] toArray(Object a[]);
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
341
Beispiel zum Prinzip der dynamischen Erweiterbarkeit
class MeinDynamischesFeld {
private Object[] daten = new Object[1];
// Datenelemente
private int anzahl = 0;
// Elementanzahl für aktuelle Belegung
public boolean add(Object element) {
if(anzahl == daten.length)
erweitere();
obj[anzahl++] = element;
return true;
}
public Object get(int index) {
if((index < 0) || (index >= anzahl))
return null;
return obj[index];
}
//
//
//
//
genug Platz?
nein! Feld vergrößern
Datenelement abspeichern
Element eingefügt
// Zulässiger Index?
// Element zurückgeben
private void erweitere() {
Object[] tmp = new Object[obj.length+1];
// größeres Feld anlegen
for(int i=0; i<obj.length; i++)
tmp[i] = obj[i];
// Daten kopieren
daten = tmp;
// neues Feld unter daten abspeichern
}
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
342
Schnittstellen- und Klassenhierarchie der Collections
Collection
List
Object
AbstractCollection
(abstract)
Dictionary
(abstract)
Map
AbstractMap
(abstract)
Set
SortedMap
HashTable
AbstractList
(abstract)
SortedSet
AbstractSet
(abstract)
HashMap
Vector
Abstract
SequentialList
(abstract)
ArrayList
TreeSet
HashSet
WeakHashMap
TreeMap
Properties
Stack
LinkedList
xyz
konkrete Klasse
x
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
y
xyz
x von y abgeleitet
abstrakte Klasse
x
Programmiersprache Java
y
xyz
Schnittstelle
x implementiert y
343
Listen
Listen sind geordnet. Man kann an einer beliebigen Stelle Objekte einfügen
oder löschen.
•
Vector, Stack und ArrayList werden intern über ein Feld
implementiert, das dynamisch neu angelegt wird, wenn zusätzlicher
Speicherplatz benötigt wird (siehe Beispiel eben zum Prinzip).
•
LinkedList wird über eine lineare Liste implementiert (siehe Vorlesung
"Einführung in die Programmierung").
•
Der Unterschied zwischen Vector und ArrayList ist nur bei mehreren
Threads von Interesse.
•
Stack arbeitet nur nach dem LIFO-Prinzip (d.h. nicht an beliebiger Stelle
Modifikation möglich).
Operationen: empty, peek, pop, push, search.
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
344
Beispiel 1: Vector
import java.util.*;
class VectorTest {
public static void main(String[] args) {
Vector vec = new Vector();
// neuen Vector-Container erzeugen
vec.add("Bryan Adams");
vec.add("Bruce Springsteen");
vec.add("Frank Sinatra");
System.out.println(vec);
//
//
//
//
vec.add(2, "Stefan Raab");
System.out.println(vec);
// An Indexposition 2 String einfügen
// [BA, BS, SR, FS]
vec.remove(3);
System.out.println(vec);
// Element an Position 3 löschen
// [BA, BS, SR]
vec.remove("Stefan Raab");
System.out.println(vec);
// Element löschen (über equals())
// [BA, BS]
Stringobjekt hinzufügen
noch einen String hinzufügen
ditto
[BA, BS, FS]
}
}
Frage:
Kann ich in obigem Programm zusätzlich noch vec.add(new Integer(5)) schreiben?
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
345
Beispiel 2: Stack
import java.util.*;
class Person {
// Beispielklasse
String name;
Person(String n) { name = n; }
void print()
{ System.out.println(name); }
}
public class StackTest {
public static void main(String[] args) {
Stack s = new Stack();
// neuen Stack-Container erzeugen
s.push(new Person("Bryan Adams"));
s.push(new Person("Bruce Springsteen"));
s.push(new Person("Frank Sinatra"));
// Objekt aus Stack legen
// noch ein Objekt hinzufügen
// ditto
while(!s.empty())
((Person)s.pop() ).print();
//
//
//
//
solange Daten auf Stack
Hole Element von Stack
und rufe Methode print() auf
Downcast nötig!
}
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
346
Beispiel 3: Liste
import java.util.*;
class Person {
// Beispielklasse
String name;
Person(String n) { name = n; }
void print()
{ System.out.println(name); }
public String toString() { return name; }
}
public class ListTest {
public static void main(String[] args) {
LinkedList l = new LinkedList();
Person p1, p2, p3;
// List-Container erzeugen
l.add(p1 = new Person("Bryan Adams"));
//
l.add(p2 = new Person("Bruce Springsteen"));//
l.add(p3 = new Person("Frank Sinatra"));
//
System.out.println(l);
//
Objekt an Liste anhängen
noch ein Objekt anhängen
ditto
[ BA, BS, FS ]
l.remove(p3);
// Franky Boy wieder löschen
System.out.println(l.contains(p2));
// Enthält Liste BS?
}
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
347
Iterator
Eine oft wiederkehrende Aufgabe bei Collections ist das Besuchen jedes
Elementes im Collection, z.B. um eine bestimmte Operation auf jedes
Datenelement anzuwenden.
Dies lässt sich im Zusammenhang mit einer Collection auf einfache Weise mit
einem Iterator machen. Dabei ist jedoch keine bestimmte Reihenfolge des
Besuchens garantiert!
public interface Iterator {
boolean hasNext();
Object next();
void remove();
}
// Optional
Anwendungsschema:
CollectionXYZ c = new CollectionXYZ();
...
Iterator it = c.iterator();
while (it.hasNext())
// solange noch unbesuchte Elemente
verarbeite(it.next());
// mache etwas mit einem unbesuchten Element
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
348
Beispiel
import java.util.*;
class Person {
String name;
int stundenlohn;
Person(String n, int knete)
int getStundenlohn()
}
// Beispielklasse
{ name = n; stundenlohn = knete; }
{ return stundenlohn; }
public class ListTest {
public static void main(String[] args) {
LinkedList l = new LinkedList();
l.add(new Person("Bryan Adams", 10));
l.add(new Person("Bruce Springsteen", 20));
l.add(new Person("Frank Sinatra", 100));
//
//
//
//
Iterator it = l.iterator();
int kosten = 0;
// Iterator anlegen
List-Container erzeugen
Objekt an Liste anhängen
noch ein Objekt anhängen
ditto
while(it.hasNext())
// noch unbesuchte Elemente?
kosten += ((Person)it.next()).getStundenlohn(); // Kosten akkumulieren
System.out.println("Kosten für Konzert: " + kosten);
}
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
349
Sets
In Sets sind wie in mathematischen Mengen keine doppelten Elemente erlaubt,
was über die Methode equals() beim Einfügen eines neuen Elements überprüft
wird. Ist das Element schon vorhanden, so liefert die add-Methode false als
Ergebnis (sonst true).
Es gibt zwei konkrete Klassen zu Set:
1.
2.
In HashSet werden die Elemente in einer Hash-Tabelle abgespeichert
(→Algorithmen und Datenstrukturen).
In TreeSet werden die Elemente sortiert in einem Binärbaum abgespeichert.
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
350
Beispiel
import java.util.*;
public class SetTest {
public static void main(String[] args) {
HashSet h = new HashSet();
h.add("Bryan Adams");
h.add("Bruce Springsteen");
// Container erzeugen
// Objekt hinzufügen
// ditto
Iterator it = h.iterator();
while(it.hasNext())
System.out.println(it.next());
// Iterator anlegen
// noch unbesuchte Elemente?
// Elemente ausgeben
TreeSet t = new TreeSet();
t.add("Bryan Adams");
t.add("Bruce Springsteen");
// Container erzeugen
// Objekt hinzufügen
// ditto
it = t.iterator();
while(it.hasNext())
System.out.println(it.next());
// Iterator anlegen
// noch unbesuchte Elemente?
// Elemente ausgeben
}
}
Ausgabe:
BS BA BA BS
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
351
Maps
Eine Map kann man sich vorstellen als eine Tabelle mit zwei Spalten: In der
ersten Spalte steht jeweils ein eindeutiger Bezeichner (Schlüssel) und in der
zweiten Spalte der dazugehörige Wert zu diesem Bezeichner. Über den Namen
kann man den Wert erfragen.
Beispiele:
•
Wörterbuch (Name, Bedeutung)
•
Umgebungsvariable in Betriebssystem-Shells (Name, Wert)
•
Klausurergebnisse (Matr.Nr., Ergebnis)
An konkreten Klassen gibt es:
•
•
•
•
HashMap, HashTable: Nutzten Hash-Verfahren zur Verwaltung der
Name-Wert-Paare
WeakHashMap: HashMap mit der Eigenschaft, dass der Garbage
Collector Einträge entfernen kann, wenn sie außerhalb der Tabelle nicht
genutzt werden
TreeMap: Nutzt einen Baum, um die Name-Wert-Paare sortiert
abzuspeichern
Properties: Einfache Ein-/Ausgabe von Name-Wert-Paaren
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
352
Beispiel
import java.util.*;
class Student {
// Beispielklasse
String name;
int matrNr;
// Schlüssel
Student(int nr, String n) {matrNr = nr; name = n; }
public String toString() { return name; }
}
public class HashMapTest {
public static void main(String[] args) {
HashMap h = new HashMap();
Student p1, p2 , p3;
// Schlüssel-Wert-Paare
h.put(new Integer(4711)
h.put(new Integer(4712)
h.put(new Integer(4713)
// Container erzeugen
einfügen. Der Schlüssel muss
, p1=new Student(4711,"Bryan
, p2=new Student(4712,"Bruce
, p3=new Student(4713,"Frank
ein Objekt sein!
Adams") );
Springsteen") );
Sinatra") );
// Student nach Matrikelnummer suchen
Student p = (Student) h.get(new Integer(4712));
System.out.println(p);
}
}
Rudolf Berrendorf
FH Bonn-Rhein-Sieg
Programmiersprache Java
353
Herunterladen