Programmieren in Java

Ähnliche Dokumente
Programmieren in Java

Programmieren in Java

Programmieren in Java

JAVA KURS COLLECTION

java.util. Sebastian Draack Department Informations- und Elektrotechnik Department Informations- und Elektrotechnik JAVA Collection-API

19 Collections Framework

19 Collections Framework

12 Collections Framework. Interfaces Maps and Collections. Collection Interface. Überblick. Collection = Containterklasse, die andere Objekte enthält.

OCP Java SE 8. Collections

Programmiertechnik II

Java Generics & Collections

Programmiertechnik II

Problem: Was ist, wenn der Stapel voll ist? Idee: Erzeuge dynamisch ein grösseres Array und kopiere um. Dynamische Anpassung der Größe

Propädeutikum Programmierung in der Bioinformatik

Einstieg in die Informatik mit Java

Kapitel 12: Java Collection Teil II

Kapitel 12: Java Collection Teil II

Java Collections Framework (JCF)

Programmiertechnik II

Rechtsbelehrung. Java und OOP Das Buch Christian Silberbauer 144

Teil V. Generics und Kollektionen in Java

Programmierkurs Java

Grundkonzepte java.util.list

Objektorientiertes Programmieren mit Java

Kapitel 5: Iterierbare Container

Vorlesung Programmieren

Kapitel 6: Java Collection Teil I

Software Entwicklung 1

Faulheit professionell: Fertige Datenbehälter. Das Java-Collections-Framework Typsicherheit Generische Klassen

ALP II Dynamische Datenmengen Datenabstraktion

Einführung in die Objektorientierte Programmierung Vorlesung 18: Lineare Datenstrukturen. Sebastian Küpper

Java Schulung. Objektorientierte Programmierung in Java Teil V: Die Java Collection Klassen. Prof. Dr. Nikolaus Wulff

Programmierkurs Java

Software Entwicklung 1

Java Einführung Collections

Programmieren in Java

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Kapitel 7: Java Collection Teil I

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 13. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 12. Listen. Listen 1

Mengen und Multimengen

Collections. Arthur Zaczek. Nov 2015

Programmieren 2 16 Java Collections und Generizität

Aufgabenblatt 4. Aufgabe 3. Aufgabe 1. Aufgabe 2. Prof. Dr. Th. Letschert Algorithmen und Datenstrukturen

Übung Algorithmen und Datenstrukturen

Einführung in die Programmierung mit Java

Javakurs für Fortgeschrittene

Lineare Datenstrukturen: Felder, Vektoren, Listen Modelle: math. Folge (a i ) i=1.. mit Basistyp T oder: [T]

Objektorientierte Programmierung. Kapitel 21: Einführung in die Collection Klassen

Programmieren I. Kapitel 13. Listen

public interface Stack<E> { public void push(e e); public E pop();

Schein-/Bachelorklausur Teil 2 am Zulassung: Mindestens 14 Punkte in Teilklausur 1 und 50% der Übungspunkte aus dem 2. Übungsblock.

Wo sind wir? Rudolf Berrendorf FH Bonn-Rhein-Sieg Programmiersprache Java 338

Collections und Iteratoren ListIterator Sets. Programmieren II. Dr. Klaus Höppner. Hochschule Darmstadt Sommersemester / 22

Programmieren II. Hierarchie von Collections. Vorlesung 3. Handout S. 1. Dr. Klaus Höppner. Hochschule Darmstadt Sommersemester 2010

Programmieren in Java

Nützliche Utility-Klassen des JDK

Collections. Arthur Zaczek

Kapitel 4: Bäume i. 1. Einleitung. 2. Ein Datenmodell für Listen. 3. Doppelt-verkettete Listen. 4. Bäume. 5. Das Collections-Framework in Java

Vorlesung Programmieren

17. Java Collections. Daten Organisieren. Generische Liste in Java: java.util.list. Typ Parameter (,,Parametrischer Polymorphisums )

ADT: Java Collections und ArrayList

Grundlagen der Informatik Generische Klassen

Programmieren in Java

Algorithmen und Datenstrukturen CS1017

Probleme ohne generische Typen

Neuere Sprachelemente in Java

Hashmap: Video Erklärung

Stacks, Queues & Bags. Datenstrukturen. Pushdown/Popup Stack. Ferd van Odenhoven. 19. September 2012

Selbststudium OOP7 & ALG2 Auftrag

Programmieren 2 02 Maps, Sets, Defensive Programmierung

12.3 Ein Datenmodell für Listen

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 4 ArrayList, PriorityQueue, HashSet und HashMap

Algorithmen und Datenstrukturen in Java Jiri Spale, Algorithmen und Datenstrukturen in Java 1

Programmierzertifikat Objekt-Orientierte Programmierung mit Java

Java Generics & Collections

Mengen und Multimengen

Info B VL 14: Java Collections/Reflections

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

7. Verkettete Strukturen: Listen

TU München, Fakultät für Informatik Lehrstuhl III: Datenbanksysteme Prof. Alfons Kemper, Ph.D.

Effiziente verkettete Listen

1. Welches Interface ist nicht von Collection abgeleitet? A. B. C. D. List Set Map SortedSet. 2. Welche Aussagen sind richtig?

Effiziente verkettete Listen

Graphdurchmusterung, Breiten- und Tiefensuche

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

1. Die rekursive Datenstruktur Liste

Datenstrukturen. Ziele

Programmieren 2 15 Abstrakte Datentypen

Realisierungsmöglichkeiten für parametrische Polymorphie

Kapitel 14. Das Java Collection Interface. Fachgebiet Knowledge Engineering Prof. Dr. Johannes Fürnkranz

Übung Algorithmen und Datenstrukturen

Die Java - Collections API

16. Dynamische Datenstrukturen

Transkript:

Datenstrukturen

2 Wiederholung: Typvariable Analog zu Variablen, die für Daten stehen, stehen Typvariablen für einen bestimmten Typ Typvariablen werden im in der Klassendefinition nach dem Klassennamen angegeben Es können beliebig viele Variablen definiert werden MODIFIKATOREN interface class BEZEICHNER < T1, T2,, T_N > { } public interface Garbage<T> { } Implementiert eine Klasse ein generisches Interface oder erweitert eine generische Klasse, so können die Typparameter weitergereicht werden: public class MyGarbage<T> implements Garbage<T> { } Sobald eine Instanz einer generischen Klasse erzeugt werden soll, muss die Typvariable konkretisiert werden: Garbage<String> mülleimer = new MyGarbage<>();

3 Wiederholung: Typvariable Lässt man die Konkretisierung gänzlich weg, so leitet der Compiler Object ab Garbage mülleimer = new MyGarbage(); Garbage<Object> mülleimer = new MyGarbage<>(); Wird ein generischen Interface implementiert oder eine generische Klasse erweitert und keine Typvariable definiert, so muss das Interface oder die Klasse konkretisiert werden public class MyGarbage imoplements Garbage<String> { } Wenn der konkrete Typ einer generischen Variable nicht interessiert, kann diese mit? als sogenannte Wildcard definiert werden Garbage<Garbage<?>> mülleimer; mülleimer = MyGarbage<Garbage<?>>(); mülleimer.add(new MyGarbage<String>()); mülleimer.add(new MyGarbage<Ware>()); Typvariablen können eingeschränkt werden public interface Garbage<T extends Disposable> { }

4 Was bisher geschah Bisher wurden zur Gruppierung von Daten immer Arrays genutzt Bis auf die Index-Funktion gibt es allerdings keinerlei logischer Operationen, mit denen der Array manipuliert werden könnte Wenn die zu organisierende Menge dynamisch ist, machen Arrays einem das Leben daher schwer: Arrays sind statisch: Länge einmal festgelegt, nicht mehr änderbar Mal eben ein Element hinzufügen oder entfernen ist aufwändig Zumeist muss der Array-Inhalt kopiert werden Große Arrays großer Kopieraufwand Datentypen, die eine Menge an Daten gruppieren und auf dieser Gruppierung eine gewisse Logik bereitstellen werden Datenstrukturen genannt Datenstrukturen & Algorithmen meist eine eigene Vorlesung!

5 Lauf- und Zugriffszeit Wichtige Punkte bei der Auswahl einer Datenstruktur sind Laufzeit: Die Anzahl der Schritte, um ein bestimmtes Element zu finden Zugriffszeit: Schritte, um auf ein bestimmtes Element zuzugreifen Beispiel Array: Zugriffszeit (Voraussetzung: Element ist enthalten): Array liegt aneinander gereiht im Speicher Zugriff: Adresse des 1. Elementes + (Position*Speichergröße(Typ)) Zugriff in einem Schritt (Notation: Ɵ(1), konstante Zugriffszeit ) Laufzeit: Im schlechtesten Fall ist das Element nicht vorhanden Um dies festzustellen muss es mit allen Elementen verglichen werden Zugriff in n-schritten (Ɵ(n), n ist die Anzahl der Elemente, lineare Laufzeit )

6 Collection-API Java bietet mit der Collection-API einen Basissatz an Datenstrukturen All diese Strukturen sind dynamisch und damit flexibler als Arrays Jede der Strukturen basiert auf einem der folgenden Interfaces Collection: Interface für Listen bzw. Mengen Map: Interface für eine Gruppe assoziativ angeordneter Elemente Sowohl Collection als auch Map sind generisch, d.h. der Datentyp der Inhalte kann generisch spezifiziert werden: Collection<String> list = new LinkedList<String>(); LinkedList ist eine Implementierung von Collection Diese Kollektion nimmt demnach nur Daten vom Typ String auf

7 Das Interface Collection public interface Collection<E> extends Iterable<E> { boolean add(e e); boolean addall(collection<? extends E> c); boolean remove(object o); boolean removeall(collection<?> c); boolean retainall(collection<?> c); boolean contains(object o); boolean containsall(collection<?> c); int size(); boolean isempty(); void clear(); Object[] toarray(); <T> T[] toarray(t[] a); Iterator<E> iterator(); }

8 Das Interface Collection Jede Implementierung des Collection-Interfaces unterstützt das Hinzufügen und Entfernen von Elementen (einzeln oder massenhaft) Überprüfen ob gewisse Inhalte vorhanden sind Abfragen der Größe Umwandeln in einen Array Desweiteren erweitert Collection das Interface Iterable Dies schreibt die Methode iterator() vor Alle Klassen, die dieses Interface implementieren können in der foreach-schleife genutzt werden: Collection<String> list = new LinkedList<>(); list.add("..."); list.add("..."); for (String element : list) System.out.println(element);

9 Listen Listen sind Collections mit einer Ordnungshierarchie Von allen Datenstrukturen am ähnlichsten zu Arrays Auf einen bestimmten Inhalt innerhalb der Liste kann über seinen Index (~ Position) zugegriffen werden List<String> list = new LinkedList<>(); list.set(0, "..."); // Füllen String fragment = list.get(3); String[] array = new String[ ]; array[0] = "..."; // Füllen String fragment = array[3]; List ist ein Interface mit verschiedenen bereits vorhandenen Implementierungen: ArrayList: das dynamische Pendant zum Array Vector: siehe ArrayList LinkedList: Die Elemente sind miteinander verkettet (nächste Folie) Sowohl ArrayList als auch Vector greifen intern auf Arrays zurück Die Unterschiede liegen in der Thread-Sicherheit (Vector) und der Art und Weise wie der interne Array verwaltet wird

10 LinkedList Jedes Element in der LinkedList wird in einem Node gespeichert Jeder Node kennt seinen Vorgänger und seinen Nachfolger Der erste und letzte Node sind in der Liste verlinkt Node first last data

11 Lauf- und Zugriffzeit (ArrayList, LinkedList) ArrayList/Vector: Intern werden die Elemente in einem Array gespeichert Zugriffszeit: Ɵ(1) Laufzeit: Ɵ(n) LinkedList Elemente sind verkettet Kein direkter Zugriff Um das n-te Element zu erreichen, muss die Kette vom ersten bis zum n-1 Element durchlaufen werden Zugriffszeit: Ɵ(n) Im schlechtesten Fall ist ein gesuchtes Element nicht vorhanden Es muss die gesamte Kette durchlaufen werden, um dies festzustellen Laufzeit: Ɵ(n)

12 LinkedList Suche eines Elements in einer LinkedList ist vergleichsweise langsam Das Löschen und Hinzufügen jedoch ist schneller als bei ArrayList/Vector Da jeder Node seinen Vorgänger und Nachfolger kennt, lassen sich beide Operationen durch umbiegen der Verlinkung in einem Schritt durchführen ArrayList/Vector müssen die richtige Stelle zum Löschen finden, den Array unter Umständen kopieren und neufüllen Löschen first last Hinzufügen first last

13 Stack Ein Stack ist bereits im Kapitel Speichermanagement aufgetaucht Der Stack-Speicher baute sich Frame für Frame auf einer Seite des Speichers auf Nach jedem Methodenende wird der Stack auf genau der Seite wieder abgebaut Die Stack-Datenstruktur ist analog aufgebaut Auch LIFO (Last-In-Firs t-out) genannt boolean empty(); E peek(); E pop(); E push(e o); int search(object o); peek() pop() push(object) Zugriff: Ɵ(1) (es ist immer nur das letzte Element zugreifbar!) Laufzeit: Ɵ(n) (es müssen alle Elemente verglichen werden)

14 Queue Ähnlich dem Stack Eine Queue (Warteschlange) wird hinten auf- und vorne abgebaut Daher: FIFO (First-In-First-Out) E element(); boolean offer(e o); E peek(); E poll(); E remove(); element()/peek() offer(object) poll()/remove() Zugriff: Ɵ(1), Laufzeit: Ɵ(n) (beides, analog zum Stack)

15 Set Spezielle Collection mit der Einschränkung: Jedes Element in der Menge ist eindeutig, d.h. es gibt keine zwei Element e1 und e2 für die gilt e1.equals(e2) == true Sets müssen nicht zwangsläufig geordnet sein Zugriffs- und Laufzeit variieren wie schon bei der Liste je nach Implementierung

16 Map Der Datentyp Map wird auch als assoziativer Speicher bezeichnet Jedes Element in der Map ist eindeutig über einen Schlüssel assoziiert Eine Map enthält demnach Schlüssel-Wert Paare Key 1 Value 1 Key 2 Value 2 Key 3 Value 3 Key 4 Value 4 Key n Value n public interface Map<K, V> { int size(); boolean isempty(); boolean containskey(object key); boolean containsvalue(object value); V get(object key); V put(k key, V value); V remove(object key); void putall(map<? extends K,? extends V> map); void clear(); Set<K> keyset(); Collection<V> values(); Set<Map.Entry<K, V>> entryset; }

17 HashMap Intern verwaltet als Array Eine Hashfunktion weißt jedem Schlüssel einen eindeutigen Index zu Eingabe der Hashfunktion ist der Hashwert (hashcode()) eines Objektes Schwierigkeit: Hashfunktion sollte injektiv sein, damit nicht zwei verschiedenen Schlüsseln der gleiche Index zugewiesen wird Eine HashMap ist unsortiert In der Regel keine Rückwärtsassoziation zwischen Wert und Schlüssel Zugriffszeit: Schlüssel wird über die Hashfunktion zu Index des internen Arrays Ɵ(1) Laufzeit: Suche nach Schlüssel: Schlüssel Hashfunktion Index Array[Index] Ɵ(1) Suche nach Wert: Ɵ(n)

18 TreeMap Schlüssel und Wert in einem Knoten gespeichert (vgl. LinkedList ) Jeder Knoten hat zwei Kindknoten Links: Schlüssel ist kleiner als der eigene Schlüssel Rechts: Schlüssel ist größer als der eigene Schlüssel Neue Elemente werden an den Blattknoten eingefügt (evtl. Umsortieren) Beispiel: Suche nach Pampelmuse H < M Schlüssel Mandarine data Daten T > M Himbeere data Traube data Ananas Kiwi Pampelmuse Zwetschge data data data data Lauf/Zugriffszeit: Ɵ(log(n)) (ohne Beweis)

19 Immutable/Hash/Equals Objekte werden als immutable bezeichnet, wenn sie nach ihrer Erzeugung nicht mehr geändert werden können Beispiel: Strings Solange ein Objekt sich nicht ändert, muss seine hashcode-methode immer den gleichen Wert liefern Wenn zwei Objekte unter equals gleich sind, müssen Ihre Hash-Werte übereinstimmen Die equals-methode wird daher häufig in Abhängigkeit zu Attributwerten definiert Hier ist vor allem im Hinblick auf HashMaps und Sets Vorsicht geboten: Da die Eindeutigkeitsforderung auf Basis von equals überprüft wird, sollten Sets nur unveränderbare Werte enthalten In Hashes werden die Werte über den Hash-Wert eines Schlüssel assoziiert, auch hier sollte der Hash-Wert und damit der Schlüssel nicht veränderbar sein

20 Iterator Zu Anfang wurde erwähnt, das Collections das Iterable-Interface implementieren So sind Collections für die foreach-schleife einsetzbar Jede Collection bietet mit iterator() allerdings die Möglichkeit direkt auf einen Iterator zuzugreifen: Iterator<String> iterator = list.iterator(); String string; while (iterator.hasnext()) { string = iterator.next(); iterator.remove(); } Vorteil: Die meisten Iterator bieten die Möglichkeit während der Iteration Einträge aus der Collection zu löschen In einer foreach-schleife nicht möglich: ConcurrentModificationException

21 Generics/Wildcards Zurück zur Definition des Collection-Interfaces public interface Collection<E> extends Iterable<E> { boolean addall(collection<? extends E> c); } Mit extends konnten generische Datentypen eingeschränkt werden Hier wird extends dazu genutzt, um eine Wildcard einzuschränken Die Methode addall akzeptiert also alle Collections, die mindestens Daten vom Typ E enthalten Aber warum genügt nicht: boolean addall(collection<e> c);

22 Generics/Wildcards Angenommen: List<Comparable> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); public static void sort(list<comparable> list) {Collections.sort(list);} Die Signatur von String: public final class String implements Comparable<String>, Es gilt also: String ist vom Typ Comparable Invarianz: List<Comparable> nicht durch List<String> ersetzbar Die sort-methode ist daher auf List<Comparable> eingeschränkt Während diese Einschränkung zu restriktiv ist, würde eine einfache Wildcard nicht garantieren, dass nur Comparable Objekte in der Liste sind Daher besteht die Möglichkeit auch Wildcards einzuschränken: public static void sort(list<? extends Comparable> list) {Collections.sort(list);}

23 Generics/Wildcards Angenommen: public static void extract( Comparable data, List<? extends Comparable> src, List<? extends Comparable> dest ) extract soll alle Daten aus src nach dest kopieren, die gleich data sind Der Versuch Daten aus src nach dest zu kopieren, wird zum Compiler-Fehler führen Beispiel: List<String> src = new ArrayList<>(); List<Integer> dest = new ArrayList<>(); String und Integer sind beide vom Typ Comparable Integer ist allerdings nicht vom Typ String Ein String-Objekt kann nicht ein eine Integer-Liste einfügt werden Compiler kann nicht sicherstellen, dass src und dest kompatibel sind

24 Generics/Wildcards Mit super können Wildcards nach oben beschränkt werden: public static void extract( Comparable data, List<? extends Comparable> src, List<? super Comparable> dest ) Nach oben heißt: Comparable oder alle Superklassen Der Compiler weiß nun, dass die Typsicherheit auf jeden Fall nicht durchbrochen wird: Objekte aus src sind Comparable und dest enthält maximal Comparable List<String> src = new ArrayList<>(); List<Object> dest = new ArrayList<>(); Faustregel: Zum lesenden Zugriff: extends Zum schreibenden Zugriff: super