Update of exercises

master
Thomas Smits 2024-01-21 13:36:56 +01:00
parent be9591d745
commit 54d2661c66
150 changed files with 681 additions and 2137 deletions

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,23 +1,51 @@
# Eine vorhandene Enumeration nutzen # Assignment: Stein, Papier, Schere, Echse, Spock
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Syntax von Enumerationen verstehen und einfache Einsatzzwecke kennenlernen. Mit Enumerationen arbeiten.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.enums.verwenden](../sources/src/main/java/pr2/enums/verwenden/). Gehen Sie in das Paket [pr2.enums.schnick](../sources/src/main/java/pr2/enums/schnick).
In dieser Aufgabe sollen Sie mit einer vorhandenen Enumeration experimentieren. Sehen Sie sich hierzu die vorhandenen Klassen an. Insbesondere das Sprite `Professor`. ![Regeln für Schnick-Schnack-Schnuck](img/schnick.png)
Im Konstruktor von `Professor` wird eine Enumeration namens `BoundaryPolicy` genutzt. Schauen Sie sich die JavaDoc der Enumeration an und versuchen Sie zu verstehen, was gemeint ist. Schreiben Sie ein einfaches Spiel (Klasse `SchnickSchnackSchnuck`), bei dem Sie gegen den Computer Schnick-Schnack-Schnuck spielen (auch Rock, Paper, Scissors genannt) mit folgenden Eigenschaften:
Testen Sie nun die verschiedenen Werte der Enumeration durch und betrachten Sie, wie sich das Sprite anders verhält. * Das Spiel geht über drei Runden.
* Es fragt den Spieler nach seiner Auswahl (r, p, s).
* Der Computer zieht zufällig eine der drei Möglichkeiten.
* Nach jeder Runde sagt das Spiel, wer welche Möglichkeit gewählt hat und wer die Runde gewonnen hat.
* Ein Sieg bringt einen Punkt, ein Unentschieden 0 Punkte.
* Die Punkte jeder Runde werden addiert.
* Am Ende wird der Gesamtpunktestand ausgegeben.
Überlegen Sie, warum hier eine Enumeration verwendet wurde und nicht etwas Vererbung mit dem Überschreiben von Methoden. Eine beispielhafte Session mit dem Programm sieht dann wie folgt aus:
## Abgabe ```console
Runde 1: Dein Zug ([r]rock, [p]aper, [s]cissors)? r
Der Computer hat gewonnen - Du: ROCK, Computer: PAPER - [0:1]
Für diese Aufgabe ist keine Abgabe vorgesehen. Runde 2: Dein Zug ([r]rock, [p]aper, [s]cissors)? p
Unentschieden - Du: PAPER, Computer: PAPER - [0:1]
Runde 3: Dein Zug ([r]rock, [p]aper, [s]cissors)? s
Du hast gewonnen: Du: SCISSORS, Computer: PAPER - [1:1]### Abgabe
Ergebnis - Du 1 Punkt(e), Computer 1 Punkt(e)
```
Repräsentieren Sie die Züge mithilfe einer Enumeration `Move`. Diese soll auch die Tasten beinhalten, welche man für die einzelnen Züge (`r`, `p`, `s`) drücken muss.
## Abgabe (optional)
__Sie müssen keine Lösung für diese Aufgabe einreichen.__
Sie können Ihre Lösung aber auf die Konformität mit den Programmierstandards testen. Hierzu gehen Sie wie folgt vor:
1. Öffnen Sie eine Kommandozeile (Terminal).
2. Gehen Sie in Ihr Working Directory.
3. Wechseln Sie mit `cd` in das Verzeichnis `sources`.
4. Bauen Sie das Projekt mit dem Kommando `mvn`.

View File

@ -1,5 +1,5 @@
# Lösung: Eine vorhandene Enumeration nutzen # Lösung: Stein, Papier, Schere, Echse, Spock
Musterlösung: Musterlösung:
[pr2.enums.verwenden](../../solutions/src/main/java/pr2/enums/verwenden/) [pr2.enums.schnick](../../solutions/src/main/java/pr2/enums/schnick).

View File

@ -1,42 +1,20 @@
# Assignment: Stein, Papier, Schere, Echse, Spock # Ausnahmen testen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Mit Enumerationen arbeiten. Bei einer gegebenen Klasse Testfälle mit JUnit schreiben, die auf das Werfen von Ausnahmen testen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.enums.schnick](../sources/src/main/java/pr2/enums/schnick). Gehen Sie in das Paket [pr2.exceptions.ausnahmen_testen](../sources/src/main/java/pr2/exceptions/ausnahmen_testen/).
![Regeln für Schnick-Schnack-Schnuck](img/schnick.png) Sie finden in der Aufgabe eine einfache Implementierung einer [Caesar-Verschlüsselung](https://de.wikipedia.org/wiki/Caesar-Verschlüsselung) in der Klasse `CrypterCaesar`. Außerdem finden Sie noch einen JUnit-Test in dem entsprechenden Paket `test`.
Schreiben Sie ein einfaches Spiel (Klasse `SchnickSchnackSchnuck`), bei dem Sie gegen den Computer Schnick-Schnack-Schnuck spielen (auch Rock, Paper, Scissors genannt) mit folgenden Eigenschaften: Im JUnit-Test `CaesarTest` fehlen aber noch die Tests für die Ausnahmen. Diese werden geworfen, wenn die übergebenen Schlüssel bzw. die Klar- und Cypher-Texte nicht den Vorgaben entsprechen. Lesen Sie daher sorgfältig die JavaDoc der Klasse `CrypterCaesar` und fügen Sie dann entsprechende Testfälle in `CaesarTest` hinzu, die auf das korrekte Werfen der Ausnahmen testen.
* Das Spiel geht über drei Runden. Lassen Sie Ihre Unit-Tests laufen und testen Sie, ob die Ausnahmen entsprechend der Vorgaben aus der JavaDoc geworfen werden.
* Es fragt den Spieler nach seiner Auswahl (r, p, s).
* Der Computer zieht zufällig eine der drei Möglichkeiten.
* Nach jeder Runde sagt das Spiel, wer welche Möglichkeit gewählt hat und wer die Runde gewonnen hat.
* Ein Sieg bringt einen Punkt, ein Unentschieden 0 Punkte.
* Die Punkte jeder Runde werden addiert.
* Am Ende wird der Gesamtpunktestand ausgegeben.
Eine beispielhafte Session mit dem Programm sieht dann wie folgt aus:
```console
Runde 1: Dein Zug ([r]rock, [p]aper, [s]cissors)? r
Der Computer hat gewonnen - Du: ROCK, Computer: PAPER - [0:1]
Runde 2: Dein Zug ([r]rock, [p]aper, [s]cissors)? p
Unentschieden - Du: PAPER, Computer: PAPER - [0:1]
Runde 3: Dein Zug ([r]rock, [p]aper, [s]cissors)? s
Du hast gewonnen: Du: SCISSORS, Computer: PAPER - [1:1]### Abgabe
Ergebnis - Du 1 Punkt(e), Computer 1 Punkt(e)
```
Repräsentieren Sie die Züge mithilfe einer Enumeration `Move`. Diese soll auch die Tasten beinhalten, welche man für die einzelnen Züge (`r`, `p`, `s`) drücken muss.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Stein, Papier, Schere, Echse, Spock # Lösung: Ausnahmen testen
Musterlösung: Musterlösung:
[pr2.enums.schnick](../../solutions/src/main/java/pr2/enums/schnick). [pr2.exceptions.ausnahmen_testen](../../solutions/src/main/java/pr2/exceptions/ausnahmen_testen/)

View File

@ -1,20 +1,24 @@
# Ausnahmen testen # Eigene Ausnahmen schreiben und an entsprechender Stelle werfen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Bei einer gegebenen Klasse Testfälle mit JUnit schreiben, die auf das Werfen von Ausnahmen testen. Ausnahmen programmieren und sinnvoll einsetzen. Bedeutung der Schlüsselwörter `throws` und `throw` verstehen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.exceptions.ausnahmen_testen](../sources/src/main/java/pr2/exceptions/ausnahmen_testen/). Gehen Sie in das Paket [pr2.exceptions.eigene_ausnahme](../sources/src/main/java/pr2/exceptions/eigene_ausnahme/).
Sie finden in der Aufgabe eine einfache Implementierung einer [Caesar-Verschlüsselung](https://de.wikipedia.org/wiki/Caesar-Verschlüsselung) in der Klasse `CrypterCaesar`. Außerdem finden Sie noch einen JUnit-Test in dem entsprechenden Paket `test`. In der vorliegenden Aufgabe sollen Sie eine Sicherung (`Fuse`) programmieren. Sicherungen gibt es (in unserer Modellwelt) nur für 16, 25 und 32 Ampére.
Im JUnit-Test `CaesarTest` fehlen aber noch die Tests für die Ausnahmen. Diese werden geworfen, wenn die übergebenen Schlüssel bzw. die Klar- und Cypher-Texte nicht den Vorgaben entsprechen. Lesen Sie daher sorgfältig die JavaDoc der Klasse `CrypterCaesar` und fügen Sie dann entsprechende Testfälle in `CaesarTest` hinzu, die auf das korrekte Werfen der Ausnahmen testen. Beim Anlegen erfährt die Sicherung über den Konstruktor bei welchem Strom sie auslösen soll. Hierbei soll es nur möglich sein, Sicherungen in den vorhandenen Stärken anzulegen. Bei jedem anderen Wert soll der Konstruktor eine `IllegalCurrentException` werfen. In der Ausnahme soll gespeichert werden, mit welchem (falschen) Wert die Sicherung angelegt werden sollte. Diese Information wird beim Aufruf von `toString()` auf der Ausnahme wieder zurückgegeben.
Lassen Sie Ihre Unit-Tests laufen und testen Sie, ob die Ausnahmen entsprechend der Vorgaben aus der JavaDoc geworfen werden. Die Sicherung wird benutzt, indem die `use`-Methode mit dem aktuellen Strom aufgerufen wird. Ist dieser größer als der Nennstrom der Sicherung löst diese aus und wirft eine `FuseTrippedException`. In der Ausnahme sind sowohl der Nennstrom als auch der Auslösestrom gespeichert und werden in der `toString`-Methode ausgegeben.
Beachten Sie die TODO-Kommentare und passen Sie das Programm entsprechend an, damit es die oben beschriebenen Anforderungen erfüllt.
Kommentieren Sie die Tests ein und lassen Sie diese laufen. Erst wenn alle Tests grün sind, gilt die Aufgabe als bestanden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Ausnahmen testen # Lösung: Eigene Ausnahmen schreiben und an entsprechender Stelle werfen
Musterlösung: Musterlösung:
[pr2.exceptions.ausnahmen_testen](../../solutions/src/main/java/pr2/exceptions/ausnahmen_testen/) [pr2.exceptions.eigene_ausnahme](../../solutions/src/main/java/pr2/exceptions/eigene_ausnahme/)

View File

@ -1,24 +1,16 @@
# Eigene Ausnahmen schreiben und an entsprechender Stelle werfen # Eigene Exception schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Ausnahmen programmieren und sinnvoll einsetzen. Bedeutung der Schlüsselwörter `throws` und `throw` verstehen. Eigene Exceptions entwerfen und verwenden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.exceptions.eigene_ausnahme](../sources/src/main/java/pr2/exceptions/eigene_ausnahme/). Gehen Sie in das Paket [pr2.exceptions.fakultaet](../sources/src/main/java/pr2/exceptions/fakultaet/).
In der vorliegenden Aufgabe sollen Sie eine Sicherung (`Fuse`) programmieren. Sicherungen gibt es (in unserer Modellwelt) nur für 16, 25 und 32 Ampére. Schreiben Sie bitte eine Klasse `Fakultaet`, die die Fakultät einer Zahl zwischen 0 und 20 berechnen kann. Wenn der Wertebereich über- oder unterschritten wird, soll die entsprechende Methode der Klasse eine `FakultaetException` werfen. Schreiben Sie weiterhin einen JUnit-Test, der sowohl die korrekte Funktion, als auch das Werfen der Ausnahme überprüft.
Beim Anlegen erfährt die Sicherung über den Konstruktor bei welchem Strom sie auslösen soll. Hierbei soll es nur möglich sein, Sicherungen in den vorhandenen Stärken anzulegen. Bei jedem anderen Wert soll der Konstruktor eine `IllegalCurrentException` werfen. In der Ausnahme soll gespeichert werden, mit welchem (falschen) Wert die Sicherung angelegt werden sollte. Diese Information wird beim Aufruf von `toString()` auf der Ausnahme wieder zurückgegeben.
Die Sicherung wird benutzt, indem die `use`-Methode mit dem aktuellen Strom aufgerufen wird. Ist dieser größer als der Nennstrom der Sicherung löst diese aus und wirft eine `FuseTrippedException`. In der Ausnahme sind sowohl der Nennstrom als auch der Auslösestrom gespeichert und werden in der `toString`-Methode ausgegeben.
Beachten Sie die TODO-Kommentare und passen Sie das Programm entsprechend an, damit es die oben beschriebenen Anforderungen erfüllt.
Kommentieren Sie die Tests ein und lassen Sie diese laufen. Erst wenn alle Tests grün sind, gilt die Aufgabe als bestanden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Eigene Ausnahmen schreiben und an entsprechender Stelle werfen # Lösung: Eigene Exception schreiben
Musterlösung: Musterlösung:
[pr2.exceptions.eigene_ausnahme](../../solutions/src/main/java/pr2/exceptions/eigene_ausnahme/) [pr2.exceptions.fakultaet](../../solutions/src/main/java/pr2/exceptions/fakultaet/)

View File

@ -1,16 +1,21 @@
# Eigene Exception schreiben # Handle-or-Declare-Regel anwenden
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Eigene Exceptions entwerfen und verwenden. In einem vorhandenen Programm die Ausnahmen korrekt weiter deklarieren und an den richtigen Stellen fangen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.exceptions.fakultaet](../sources/src/main/java/pr2/exceptions/fakultaet/). Gehen Sie in das Paket [pr2.exceptions.handle_or_declare](../sources/src/main/java/pr2/exceptions/handle_or_declare/).
Schreiben Sie bitte eine Klasse `Fakultaet`, die die Fakultät einer Zahl zwischen 0 und 20 berechnen kann. Wenn der Wertebereich über- oder unterschritten wird, soll die entsprechende Methode der Klasse eine `FakultaetException` werfen. Schreiben Sie weiterhin einen JUnit-Test, der sowohl die korrekte Funktion, als auch das Werfen der Ausnahme überprüft. Entfernen Sie auskommentierten Zeilen in der Klasse `Buchstabenzaehler`. Das Programm wird nicht korrekt kompilieren, weil die Ausnahmen nicht richtig deklariert und behandelt wurden.
Korrigieren Sie diesen Fehler und sorgen Sie dafür, dass die Ausnahmen an den Stellen behandelt werden, an denen Sie behandelt werden sollten, d.h. dort wo die Verursachung liegt. Bei der `StatistikException` handelt es sich um eine Inkonsistenz im Programm. Überlegen Sie, wo diese behandelt werden sollte und wann sie auftreten kann.
Sie müssen die Ausnahmen sinnvoll behandeln. Sie einfach an der `main`-Methode
zu deklarieren ist keine valide Lösung dieser Aufgabe.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Eigene Exception schreiben # Lösung: Handle-or-Declare-Regel anwenden
Musterlösung: Musterlösung:
[pr2.exceptions.fakultaet](../../solutions/src/main/java/pr2/exceptions/fakultaet/) [pr2.exceptions.handle_or_declare](../../solutions/src/main/java/pr2/exceptions/handle_or_declare/)

View File

@ -1,21 +1,20 @@
# Handle-or-Declare-Regel anwenden # Ausnahmen mit `try` und `catch` behandeln.
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
In einem vorhandenen Programm die Ausnahmen korrekt weiter deklarieren und an den richtigen Stellen fangen. Vorhandene Ausnahmen mit `try` und `catch` abfangen und behandeln.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.exceptions.handle_or_declare](../sources/src/main/java/pr2/exceptions/handle_or_declare/). Gehen Sie in das Paket [pr2.exceptions.try_catch](../sources/src/main/java/pr2/exceptions/try_catch/).
Entfernen Sie auskommentierten Zeilen in der Klasse `Buchstabenzaehler`. Das Programm wird nicht korrekt kompilieren, weil die Ausnahmen nicht richtig deklariert und behandelt wurden. Betrachten Sie das sehr einfache Zahlenraten-Spiel. Lassen Sie es laufen und spielen Sie ein paar Runden. Versuchen Sie das Programm durch falsche Eingaben zum Absturz zu bringen.
Korrigieren Sie diesen Fehler und sorgen Sie dafür, dass die Ausnahmen an den Stellen behandelt werden, an denen Sie behandelt werden sollten, d.h. dort wo die Verursachung liegt. Bei der `StatistikException` handelt es sich um eine Inkonsistenz im Programm. Überlegen Sie, wo diese behandelt werden sollte und wann sie auftreten kann. Im Augenblick werden die Ausnahmen in der `main()`-Methode weiter deklariert, was schlechter Stil ist und zu bei Falscheingaben zu Programmabstürzen führt. Ändern Sie das Programm stattdessen so ab, dass die Ausnahmen korrekt behandelt werden. Entfernen Sie danach die `throws`-Deklaration aus dem Kopf der `main()`-Methode.
Sie müssen die Ausnahmen sinnvoll behandeln. Sie einfach an der `main`-Methode Lassen Sie das Programm erneut laufen und testen Sie, ob es jetzt nach Falscheingaben immer noch abstürzt.
zu deklarieren ist keine valide Lösung dieser Aufgabe.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Handle-or-Declare-Regel anwenden # Lösung: Ausnahmen mit `try` und `catch` behandeln.
Musterlösung: Musterlösung:
[pr2.exceptions.handle_or_declare](../../solutions/src/main/java/pr2/exceptions/handle_or_declare/) [pr2.exceptions.try_catch](../../solutions/src/main/java/pr2/exceptions/try_catch/)

View File

@ -1,20 +1,29 @@
# Ausnahmen mit `try` und `catch` behandeln. # `BufferedReader` zum zeilenweisen Lesen einsetzen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Vorhandene Ausnahmen mit `try` und `catch` abfangen und behandeln. Daten Zeilenweise mit einem `BufferedReader` verwenden und dabei das Decorator Pattern einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.exceptions.try_catch](../sources/src/main/java/pr2/exceptions/try_catch/). Gehen Sie in das Paket [pr2.io.buffered_reader](../sources/src/main/java/pr2/io/buffered_reader/).
Betrachten Sie das sehr einfache Zahlenraten-Spiel. Lassen Sie es laufen und spielen Sie ein paar Runden. Versuchen Sie das Programm durch falsche Eingaben zum Absturz zu bringen. Lesen Sie die Datei [kafka.txt](../sources/src/main/resources/pr2/io/buffered_reader/kafka.txt) zeilenweise ein und geben Sie die Zeilen mit einer fortlaufenden Zeilennummer wieder aus. Verwenden Sie hierzu einen `BufferedReader`.
Im Augenblick werden die Ausnahmen in der `main()`-Methode weiter deklariert, was schlechter Stil ist und zu bei Falscheingaben zu Programmabstürzen führt. Ändern Sie das Programm stattdessen so ab, dass die Ausnahmen korrekt behandelt werden. Entfernen Sie danach die `throws`-Deklaration aus dem Kopf der `main()`-Methode. Eine beispielhafte Ausgabe sieht wie folgt aus:
Lassen Sie das Programm erneut laufen und testen Sie, ob es jetzt nach Falscheingaben immer noch abstürzt. ```console
1: Verhaftung - Gespräch mit Frau Grubach - Dann Fräulein Bürstner
2:
3: Jemand mußte Josef K. verleumdet haben, denn ohne daß er etwas Böses
4: getan hätte, wurde er eines Morgens verhaftet. Die Köchin der Frau
5: Grubach, seiner Zimmervermieterin, die ihm jeden Tag gegen acht Uhr früh
6: das Frühstück brachte, kam diesmal nicht. Das war noch niemals
```
Lassen Sie das Programm laufen und überprüfen Sie, ob die Ausgabe korrekt ist. Die Beispieldatei hat 232 Zeilen.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Ausnahmen mit `try` und `catch` behandeln. # Lösung: `BufferedReader` zum zeilenweisen Lesen einsetzen
Musterlösung: Musterlösung:
[pr2.exceptions.try_catch](../../solutions/src/main/java/pr2/exceptions/try_catch/) [pr2.io.buffered_reader](../../solutions/src/main/java/pr2/io/buffered_reader/)

View File

@ -1,29 +1,28 @@
# `BufferedReader` zum zeilenweisen Lesen einsetzen # DataOutputStream
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Daten Zeilenweise mit einem `BufferedReader` verwenden und dabei das Decorator Pattern einsetzen. Daten mit einem `DataOutputStreams` manuell serialisieren.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.buffered_reader](../sources/src/main/java/pr2/io/buffered_reader/). Gehen Sie in das Paket [pr2.io.datainputoutput_1](../sources/src/main/java/pr2/io/datainputoutput_1/).
Lesen Sie die Datei [kafka.txt](../sources/src/main/resources/pr2/io/buffered_reader/kafka.txt) zeilenweise ein und geben Sie die Zeilen mit einer fortlaufenden Zeilennummer wieder aus. Verwenden Sie hierzu einen `BufferedReader`. Schreiben Sie eine Klasse `DateWriter`, die ein Datum in der Form yyyy-MM-dd (z.B. 1997-08-29) von der Konsole annimmt und als `long`-Wert mithilfe eines `DataOutputStreams` in eine Datei schreibt.
Eine beispielhafte Ausgabe sieht wie folgt aus: Schreiben Sie eine Klasse `DateReader`, die den `long`-Wert aus der Datei ausliest und wieder in das ursprüngliche Format bringt und auf der Konsole ausgibt.
**Hinweis:** Zur Konvertierung eines Strings in ein Datum und umgekehrt, können Sie die Klasse `SimpleDateFormat` verwenden. Ein `Date`-Objekt lässt sich leicht über die Methode `getTime` in einen `long`-Wert umwandeln. Denken Sie an eine korrekte Behandlung von möglichen Fehlern.
```console ```console
1: Verhaftung - Gespräch mit Frau Grubach - Dann Fräulein Bürstner > java DateWriter 1997-08-29
2: > java DateReader
3: Jemand mußte Josef K. verleumdet haben, denn ohne daß er etwas Böses Das Datum war: 1997-08-29
4: getan hätte, wurde er eines Morgens verhaftet. Die Köchin der Frau
5: Grubach, seiner Zimmervermieterin, die ihm jeden Tag gegen acht Uhr früh
6: das Frühstück brachte, kam diesmal nicht. Das war noch niemals
``` ```
Lassen Sie das Programm laufen und überprüfen Sie, ob die Ausgabe korrekt ist. Die Beispieldatei hat 232 Zeilen. **Zusatzfrage:** Welche besondere Bedeutung hat das hier als Beispiel verwendete Datum?
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: `BufferedReader` zum zeilenweisen Lesen einsetzen # Lösung: DataOutputStream
Musterlösung: Musterlösung:
[pr2.io.buffered_reader](../../solutions/src/main/java/pr2/io/buffered_reader/) [pr2.io.datainputoutput_1](../../solutions/src/main/java/pr2/io/datainputoutput_1/)

View File

@ -1,28 +1,18 @@
# DataOutputStream # DataOutputStream durch Serialisierung ersetzen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Daten mit einem `DataOutputStreams` manuell serialisieren. Daten mit einem `ObjectOutputStreams` serialisieren.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.datainputoutput_1](../sources/src/main/java/pr2/io/datainputoutput_1/). Gehen Sie in das Paket [pr2.io.datainputoutput_2](../sources/src/main/java/pr2/io/datainputoutput_2/).
Schreiben Sie eine Klasse `DateWriter`, die ein Datum in der Form yyyy-MM-dd (z.B. 1997-08-29) von der Konsole annimmt und als `long`-Wert mithilfe eines `DataOutputStreams` in eine Datei schreibt. Verändern Sie die beiden Klassen aus der vorhergehenden Aufgabe so, dass sie jetzt anstatt eines `DataOutputStreams` bzw. eines `DataInputStreams` Serialisierung verwenden.
Schreiben Sie eine Klasse `DateReader`, die den `long`-Wert aus der Datei ausliest und wieder in das ursprüngliche Format bringt und auf der Konsole ausgibt. Vergleichen Sie bitte die Dateien, die bei diesem und der anderen Lösung entstanden sind. Was fällt ihnen auf?
**Hinweis:** Zur Konvertierung eines Strings in ein Datum und umgekehrt, können Sie die Klasse `SimpleDateFormat` verwenden. Ein `Date`-Objekt lässt sich leicht über die Methode `getTime` in einen `long`-Wert umwandeln. Denken Sie an eine korrekte Behandlung von möglichen Fehlern.
```console
> java DateWriter 1997-08-29
> java DateReader
Das Datum war: 1997-08-29
```
**Zusatzfrage:** Welche besondere Bedeutung hat das hier als Beispiel verwendete Datum?
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: DataOutputStream # Lösung: DataOutputStream durch Serialisierung ersetzen
Musterlösung: Musterlösung:
[pr2.io.datainputoutput_1](../../solutions/src/main/java/pr2/io/datainputoutput_1/) [pr2.io.datainputoutput_2](../../solutions/src/main/java/pr2/io/datainputoutput_2/)

View File

@ -1,18 +1,41 @@
# DataOutputStream durch Serialisierung ersetzen # Daten mit `DataOutputStream` und `DataInputStream` verarbeiten
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Daten mit einem `ObjectOutputStreams` serialisieren. Ein eigenes Format für die Daten einer Klasse definieren und diese Dann in einer Datei speichern und aus dieser wieder laden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.datainputoutput_2](../sources/src/main/java/pr2/io/datainputoutput_2/). Gehen Sie in das Paket [pr2.io.data_output](../sources/src/main/java/pr2/io/data_output/).
Verändern Sie die beiden Klassen aus der vorhergehenden Aufgabe so, dass sie jetzt anstatt eines `DataOutputStreams` bzw. eines `DataInputStreams` Serialisierung verwenden. In dieser Aufgabe finden Sie bereits eine fertig implementierte Klasse `Board` vor, die ein Schachbrett repräsentiert. Allerdings wird dieses nicht für Schach benutzt, sondern für ein Spiel, bei dem man nur schwarze und weiße Steine auf das Brett stellen kann (z.B. Dame). Die Farbe der Steine wird durch die Enumeration `Color` dargestellt.
Vergleichen Sie bitte die Dateien, die bei diesem und der anderen Lösung entstanden sind. Was fällt ihnen auf? Was bei dem Schachbrett allerdings noch fehlt, ist eine Möglichkeit den Spielstand zu speichern und später wieder einzulesen.
Schauen Sie sich die Klassen `Board` und `Color` genau an und versuchen Sie diese zu verstehen. Sie können auch testweise ein Brett anlegen und mit Daten befüllen. (Wie dies geht, sehen Sie im JUnit-Test). Die `toString()`-Methode liefert eine anschauliche Darstellung des Spielfeldes.
Implementieren Sie nun die Methoden `writeToFile` und `loadFromFile` unter Zuhilfenahme von `DateOutputStream` und `DataInputStream`. Hierzu müssen Sie noch das Datenformat für die Speicherung festlegen. Dieses ist wie folgt definiert:
1. Als erstes der String "Schachbrett" im UTF8-Format, um das Datenformat zu kennzeichnen.
2. Die Koordinaten der ersten Figur im Format x-Pos, y-Pos (beide als `byte`) und Farbe entsprechend `Color.ordinal()` (als `int`)
3. Wiederholung von Schritt 2. bis alle Figuren gespeichert sind.
4. Werte `0xff`, `0xff`, `-1`, um das Dateiende zu kennzeichnen
Lassen Sie den JUnit-Test laufen, um zu sehen, ob die Daten korrekt verarbeitet werden.
## Abgabe (optional)
__Sie müssen keine Lösung für diese Aufgabe einreichen.__
Sie können Ihre Lösung aber auf die Konformität mit den Programmierstandards testen. Hierzu gehen Sie wie folgt vor:
1. Öffnen Sie eine Kommandozeile (Terminal).
2. Gehen Sie in Ihr Working Directory.
3. Wechseln Sie mit `cd` in das Verzeichnis `sources`.
4. Bauen Sie das Projekt mit dem Kommando `mvn`.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: DataOutputStream durch Serialisierung ersetzen # Lösung: Daten mit `DataOutputStream` und `DataInputStream` verarbeiten
Musterlösung: Musterlösung:
[pr2.io.datainputoutput_2](../../solutions/src/main/java/pr2/io/datainputoutput_2/) [pr2.io.data_output](../../solutions/src/main/java/pr2/io/data_output/)

View File

@ -1,41 +1,24 @@
# Daten mit `DataOutputStream` und `DataInputStream` verarbeiten # Daten mit einem `InputStream` lesen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Ein eigenes Format für die Daten einer Klasse definieren und diese Dann in einer Datei speichern und aus dieser wieder laden. Einen `InputStream` benutzen, um Daten aus einer Datei zu lesen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.data_output](../sources/src/main/java/pr2/io/data_output/). Gehen Sie in das Paket [pr2.io.datei_lesen](../sources/src/main/java/pr2/io/datei_lesen/).
In dieser Aufgabe finden Sie bereits eine fertig implementierte Klasse `Board` vor, die ein Schachbrett repräsentiert. Allerdings wird dieses nicht für Schach benutzt, sondern für ein Spiel, bei dem man nur schwarze und weiße Steine auf das Brett stellen kann (z.B. Dame). Die Farbe der Steine wird durch die Enumeration `Color` dargestellt. Lesen Sie die Daten aus der Datei [daten.dat](../sources/src/main/resources/pr2/io/datei_lesen/daten.dat) byteweise und geben Sie den Inhalt auf der Konsole aus. Für die Ausgabe verwenden Sie bitte die Hexadezimale Darstellung, also z.B. `0x0a` für den Wert 11.
Was bei dem Schachbrett allerdings noch fehlt, ist eine Möglichkeit den Spielstand zu speichern und später wieder einzulesen. Lassen Sie das Programm laufen und betrachten Sie die Ausgabe. Wenn Sie alles korrekt implementiert haben, sollten Sie den Text
Schauen Sie sich die Klassen `Board` und `Color` genau an und versuchen Sie diese zu verstehen. Sie können auch testweise ein Brett anlegen und mit Daten befüllen. (Wie dies geht, sehen Sie im JUnit-Test). Die `toString()`-Methode liefert eine anschauliche Darstellung des Spielfeldes. 0xca 0xff 0xfe 0xba 0xbe 0x0 0xde 0xad 0xbe 0xef
Implementieren Sie nun die Methoden `writeToFile` und `loadFromFile` unter Zuhilfenahme von `DateOutputStream` und `DataInputStream`. Hierzu müssen Sie noch das Datenformat für die Speicherung festlegen. Dieses ist wie folgt definiert: sehen.
1. Als erstes der String "Schachbrett" im UTF8-Format, um das Datenformat zu kennzeichnen. Denken Sie auch an eine Fehlerbehandlung für eventuelle Ausnahmen im Zusammenhang mit der Datei.
2. Die Koordinaten der ersten Figur im Format x-Pos, y-Pos (beide als `byte`) und Farbe entsprechend `Color.ordinal()` (als `int`)
3. Wiederholung von Schritt 2. bis alle Figuren gespeichert sind.
4. Werte `0xff`, `0xff`, `-1`, um das Dateiende zu kennzeichnen
Lassen Sie den JUnit-Test laufen, um zu sehen, ob die Daten korrekt verarbeitet werden.
## Abgabe (optional)
__Sie müssen keine Lösung für diese Aufgabe einreichen.__
Sie können Ihre Lösung aber auf die Konformität mit den Programmierstandards testen. Hierzu gehen Sie wie folgt vor:
1. Öffnen Sie eine Kommandozeile (Terminal).
2. Gehen Sie in Ihr Working Directory.
3. Wechseln Sie mit `cd` in das Verzeichnis `sources`.
4. Bauen Sie das Projekt mit dem Kommando `mvn`.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Daten mit `DataOutputStream` und `DataInputStream` verarbeiten # Lösung: Daten mit einem `InputStream` lesen
Musterlösung: Musterlösung:
[pr2.io.data_output](../../solutions/src/main/java/pr2/io/data_output/) [pr2.io.datei_lesen](../../solutions/src/main/java/pr2/io/datei_lesen/)

View File

@ -1,24 +1,26 @@
# Daten mit einem `InputStream` lesen # Daten mit einem `OutputStream` schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen `InputStream` benutzen, um Daten aus einer Datei zu lesen. Einen `OutputStream` verwenden, um Daten zu schreiben.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.datei_lesen](../sources/src/main/java/pr2/io/datei_lesen/). Gehen Sie in das Paket [pr2.io.datei_schreiben](../sources/src/main/java/pr2/io/datei_schreiben/).
Lesen Sie die Daten aus der Datei [daten.dat](../sources/src/main/resources/pr2/io/datei_lesen/daten.dat) byteweise und geben Sie den Inhalt auf der Konsole aus. Für die Ausgabe verwenden Sie bitte die Hexadezimale Darstellung, also z.B. `0x0a` für den Wert 11. In dieser Aufgabe sollen Sie eine Reihe von Bytes in eine Datei schreiben. Ein JUnit-Test wird überprüfen, ob Sie dies richtig getan haben.
Lassen Sie das Programm laufen und betrachten Sie die Ausgabe. Wenn Sie alles korrekt implementiert haben, sollten Sie den Text Öffnen Sie einen passenden `OutputStream`, um in die Datei `output/daten.dat` zu schreiben (verwenden Sie die Konstante `FILE` für den Dateinamen). Schreiben Sie nun die Byte-Folge
```console
0xca 0xff 0xfe 0xba 0xbe 0x0 0xde 0xad 0xbe 0xef 0xca 0xff 0xfe 0xba 0xbe 0x0 0xde 0xad 0xbe 0xef
```
sehen. hinein und schließen Sie die Datei wieder.
Denken Sie auch an eine Fehlerbehandlung für eventuelle Ausnahmen im Zusammenhang mit der Datei. Führen Sie den JUnit-Test aus, der überprüft, ob alle Daten korrekt in die Datei geschrieben wurden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Daten mit einem `InputStream` lesen # Lösung: Daten mit einem `OutputStream` schreiben
Musterlösung: Musterlösung:
[pr2.io.datei_lesen](../../solutions/src/main/java/pr2/io/datei_lesen/) [pr2.io.datei_schreiben](../../solutions/src/main/java/pr2/io/datei_schreiben/)

View File

@ -1,26 +1,37 @@
# Daten mit einem `OutputStream` schreiben # Filesystem-Abstraktion mit `File`
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen `OutputStream` verwenden, um Daten zu schreiben. Die Klasse `Path` einsetzen, um plattformunabhängig Operationen auf dem Dateisystem durchzuführen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.datei_schreiben](../sources/src/main/java/pr2/io/datei_schreiben/). Gehen Sie in das Paket [pr2.io.file](../sources/src/main/java/pr2/io/file/).
In dieser Aufgabe sollen Sie eine Reihe von Bytes in eine Datei schreiben. Ein JUnit-Test wird überprüfen, ob Sie dies richtig getan haben. Benutzen Sie die Klasse `Path`, um die Festplatte Ihres Computers, ausgehend von dem als `root` bezeichneten Verzeichnis `../..` zu durchsuchen und die Größe der Verzeichnisse zu berechnen.
Öffnen Sie einen passenden `OutputStream`, um in die Datei `output/daten.dat` zu schreiben (verwenden Sie die Konstante `FILE` für den Dateinamen). Schreiben Sie nun die Byte-Folge Sie können die Größe eines Verzeichnisses nur indirekt bestimme, indem Sie die Größe aller Dateien in dem Verzeichnis addieren. Das Verzeichnis direkt kann man _nicht_ mit `size()` nach seiner Größe fragen, wohl aber normale Dateien. Deswegen müssen Sie in Ihrem Programm immer sauber unterscheiden, ob ein Verzeichnis vorliegt (das sie rekursiv durchlaufen müssen) oder eine normale Datei (deren Größe Sie abfragen).
Geben Sie die Verzeichnisse mit Ihrer Größe aus. Am Ende des Programms geben Sie noch die Gesamtgröße aller Unterverzeichnisse aus. Eine beispielhafte sähe wie folgt aus:
```console ```console
0xca 0xff 0xfe 0xba 0xbe 0x0 0xde 0xad 0xbe 0xef Untersuche: /home/thomas/eclipse-workspace
465 Byte - /home/thomas/eclipse-workspace/.recommenders/snipmatch/repositories
1,4 kByte - /home/thomas/eclipse-workspace/.recommenders/snipmatch
4,6 MByte - /home/thomas/eclipse-workspace/.recommenders
57,5 MByte - /home/thomas/eclipse-workspace
103 Byte - /home/thomas/lib/.settings
5,8 MByte - /home/thomas/lib
Gesamtgröße: 80,4 MByte
``` ```
hinein und schließen Sie die Datei wieder. Lassen Sie Ihr Programm laufen und überprüfen Sie, ob die Ausgaben plausibel sind. Vergleichen Sie das Ergebnis mit den Angaben des Windows-Explorers, Mac-Finders oder Linux-Dateimanagers.
Führen Sie den JUnit-Test aus, der überprüft, ob alle Daten korrekt in die Datei geschrieben wurden. Unter Linux und MacOS müssen Sie darauf achten, dass Sie symbolischen Links in Ihrem Programm nicht folgen, sonst zählen Sie möglicherweise zu viel.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Daten mit einem `OutputStream` schreiben # Lösung: Filesystem-Abstraktion mit `File`
Musterlösung: Musterlösung:
[pr2.io.datei_schreiben](../../solutions/src/main/java/pr2/io/datei_schreiben/) [pr2.io.file](../../solutions/src/main/java/pr2/io/file/)

View File

@ -1,38 +1,33 @@
# Filesystem-Abstraktion mit `File` # Fileattribute lesen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Die Klasse `Path` einsetzen, um plattformunabhängig Operationen auf dem Dateisystem durchzuführen. Methoden der Klassen `Path` und `Files` nutzen und verstehen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.file](../sources/src/main/java/pr2/io/file/). Gehen Sie in das Paket [pr2.io.filetest](../sources/src/main/java/pr2/io/filetest/).
Benutzen Sie die Klasse `Path`, um die Festplatte Ihres Computers, ausgehend von dem als `root` bezeichneten Verzeichnis `../..` zu durchsuchen und die Größe der Verzeichnisse zu berechnen. Schreiben Sie eine Klasse `FileInfo`, der man auf der Konsole einen Datei- oder Verzeichnisnamen übergeben kann. Sie soll dann einige grundlegende Informationen über die Datei ausgeben (siehe Beispiel).
Sie können die Größe eines Verzeichnisses nur indirekt bestimme, indem Sie die Größe aller Dateien in dem Verzeichnis addieren. Das Verzeichnis direkt kann man _nicht_ mit `size()` nach seiner Größe fragen, wohl aber normale Dateien. Deswegen müssen Sie in Ihrem Programm immer sauber unterscheiden, ob ein Verzeichnis vorliegt (das sie rekursiv durchlaufen müssen) oder eine normale Datei (deren Größe Sie abfragen).
Geben Sie die Verzeichnisse mit Ihrer Größe aus. Am Ende des Programms geben Sie noch die Gesamtgröße aller Unterverzeichnisse aus. Eine beispielhafte sähe wie folgt aus:
```console ```console
Untersuche: /home/thomas/eclipse-workspace > java FileTest /Users/thomas/Documents/../Documents/
/Users/thomas/Documents existiert
/Users/thomas/Documents ist 408 Bytes groß
/Users/thomas/Documents ist ein Verzeichnis
/Users/thomas/Documents darf gelesen werden
/Users/thomas/Documents darf geschrieben werden
465 Byte - /home/thomas/eclipse-workspace/.recommenders/snipmatch/repositories > java FileTest /Users/thomas/Documents/../Documents/Uebungsklausur.pages
1,4 kByte - /home/thomas/eclipse-workspace/.recommenders/snipmatch /Users/thomas/Documents/Uebungsklausur.pages existiert
4,6 MByte - /home/thomas/eclipse-workspace/.recommenders /Users/thomas/Documents/Uebungsklausur.pages ist 258920 Bytes groß
57,5 MByte - /home/thomas/eclipse-workspace /Users/thomas/Documents/Uebungsklausur.pages ist ein normale Datei
103 Byte - /home/thomas/lib/.settings /Users/thomas/Documents/Uebungsklausur.pages darf gelesen werden
5,8 MByte - /home/thomas/lib /Users/thomas/Documents/Uebungsklausur.pages darf geschrieben werden
Gesamtgröße: 80,4 MByte
``` ```
Lassen Sie Ihr Programm laufen und überprüfen Sie, ob die Ausgaben plausibel sind. Vergleichen Sie das Ergebnis mit den Angaben des Windows-Explorers, Mac-Finders oder Linux-Dateimanagers.
Unter Linux und MacOS müssen Sie darauf achten, dass Sie symbolischen Links in Ihrem Programm nicht folgen, sonst zählen Sie möglicherweise zu viel.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Filesystem-Abstraktion mit `File` # Lösung: Fileattribute lesen
Musterlösung: Musterlösung:
[pr2.io.file](../../solutions/src/main/java/pr2/io/file/) [pr2.io.filetest](../../solutions/src/main/java/pr2/io/filetest/)

View File

@ -1,32 +1,18 @@
# Fileattribute lesen # `FilterReader`
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Methoden der Klassen `Path` und `Files` nutzen und verstehen. Einen eigenen Filter in Form eines `FilterReaders` programmieren und hiermit in den Datenstrom eingreifen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.filetest](../sources/src/main/java/pr2/io/filetest/). Gehen Sie in das Paket [pr2.io.filter](../sources/src/main/java/pr2/io/filter/).
Schreiben Sie eine Klasse `FileInfo`, der man auf der Konsole einen Datei- oder Verzeichnisnamen übergeben kann. Sie soll dann einige grundlegende Informationen über die Datei ausgeben (siehe Beispiel). Vervollständigen Sie die Klasse `UCaseReader` so, dass Sie als Filter (`FilterReader`) verwendet werden kann. Die Aufgabe dieses Filters besteht darin, alle gelesenen Zeichen in Großbuchstaben umzuwandeln.
```console Testen Sie, ob Ihre Implementierung korrekt ist, indem Sie die JUnit-Tests ausführen.
> java FileTest /Users/thomas/Documents/../Documents/
/Users/thomas/Documents existiert
/Users/thomas/Documents ist 408 Bytes groß
/Users/thomas/Documents ist ein Verzeichnis
/Users/thomas/Documents darf gelesen werden
/Users/thomas/Documents darf geschrieben werden
> java FileTest /Users/thomas/Documents/../Documents/Uebungsklausur.pages
/Users/thomas/Documents/Uebungsklausur.pages existiert
/Users/thomas/Documents/Uebungsklausur.pages ist 258920 Bytes groß
/Users/thomas/Documents/Uebungsklausur.pages ist ein normale Datei
/Users/thomas/Documents/Uebungsklausur.pages darf gelesen werden
/Users/thomas/Documents/Uebungsklausur.pages darf geschrieben werden
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Fileattribute lesen # Lösung: `FilterReader`
Musterlösung: Musterlösung:
[pr2.io.filetest](../../solutions/src/main/java/pr2/io/filetest/) [pr2.io.filter](../../solutions/src/main/java/pr2/io/filter/)

View File

@ -1,18 +1,20 @@
# `FilterReader` # Konsolen Input/Output
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen eigenen Filter in Form eines `FilterReaders` programmieren und hiermit in den Datenstrom eingreifen. Daten von der Konsole lesen und über eine Ausgabeumlenkung in eine Datei umlenken. `PrintStream` und `InputStreamReader` einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.filter](../sources/src/main/java/pr2/io/filter/). Gehen Sie in das Paket [pr2.io.konsole](../sources/src/main/java/pr2/io/konsole/).
Vervollständigen Sie die Klasse `UCaseReader` so, dass Sie als Filter (`FilterReader`) verwendet werden kann. Die Aufgabe dieses Filters besteht darin, alle gelesenen Zeichen in Großbuchstaben umzuwandeln. Lesen Sie zeilenweise mithilfe eines `BufferedReaders` von der Konsole Zeichen ein. Geben Sie diese wieder auf `System.out` aus und zeigen Sie die aktuelle Zeilennummer auf `System.err` an.
Testen Sie, ob Ihre Implementierung korrekt ist, indem Sie die JUnit-Tests ausführen. Testen Sie das Programm.
Lenken Sie nun die Ausgabe von `System.out` in die Datei `output/console.log` um (siehe Konstante `LOGFILE`). Lassen Sie das Programm erneut laufen und betrachten Sie danach die Datei mit den umgeleiteten Daten.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: `FilterReader` # Lösung: Konsolen Input/Output
Musterlösung: Musterlösung:
[pr2.io.filter](../../solutions/src/main/java/pr2/io/filter/) [pr2.io.konsole](../../solutions/src/main/java/pr2/io/konsole/)

View File

@ -1,20 +1,21 @@
# Konsolen Input/Output # Zeilen einer Textdatei zählen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Daten von der Konsole lesen und über eine Ausgabeumlenkung in eine Datei umlenken. `PrintStream` und `InputStreamReader` einsetzen. Dateien zeilenweise lesen und verarbeiten.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.konsole](../sources/src/main/java/pr2/io/konsole/). Gehen Sie in das Paket [pr2.io.linecounter](../sources/src/main/java/pr2/io/linecounter/).
Lesen Sie zeilenweise mithilfe eines `BufferedReaders` von der Konsole Zeichen ein. Geben Sie diese wieder auf `System.out` aus und zeigen Sie die aktuelle Zeilennummer auf `System.err` an. Schreiben Sie eine Klasse `LineCounter`, die den Namen einer Textdatei von der Kommandozeile entgegennimmt und dann die Anzahl der Zeilen in der Datei ausgibt.
Testen Sie das Programm. ```console
> java LineCounter ../src/LineCounter.java
Lenken Sie nun die Ausgabe von `System.out` in die Datei `output/console.log` um (siehe Konstante `LOGFILE`). Lassen Sie das Programm erneut laufen und betrachten Sie danach die Datei mit den umgeleiteten Daten. Datei: ../src/LineCounter.java hat 30 Zeilen
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Konsolen Input/Output # Lösung: Zeilen einer Textdatei zählen
Musterlösung: Musterlösung:
[pr2.io.konsole](../../solutions/src/main/java/pr2/io/konsole/) [pr2.io.linecounter](../../solutions/src/main/java/pr2/io/linecounter/)

View File

@ -1,21 +1,22 @@
# Zeilen einer Textdatei zählen # `RandomAccessFile`
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Dateien zeilenweise lesen und verarbeiten. `RandomAccessFile` sowohl zum Lesen, als auch zum Schreiben von Daten einsetzen. Verstehen, dass man sich wahlfrei durch die Datei bewegen kann.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.linecounter](../sources/src/main/java/pr2/io/linecounter/). Gehen Sie in das Paket [pr2.io.random_access](../sources/src/main/java/pr2/io/random_access/).
Schreiben Sie eine Klasse `LineCounter`, die den Namen einer Textdatei von der Kommandozeile entgegennimmt und dann die Anzahl der Zeilen in der Datei ausgibt. Bei dieser Aufgabe werden Sie ein Verfahren anwenden, das bei sehr großen Datenmengen zum Einsatz kommt: das Sortieren der Daten direkt auf der Festplatte, ohne sie vollständig in den Hauptspeicher zu laden.
```console Implementieren Sie einen [Bubblesort](https://de.wikipedia.org/wiki/Bubblesort) mithilfe von `RandomAccessFile` direkt auf einer Datei. Bubblesort ist ein ausgesprochen ineffizienter Algorithmus (O(n*n)), er ist aber sehr einfach zu implementieren. Da die zu sortierende Datei klein ist, können wir hier mit den Nachteilen von Bubblesort leben.
> java LineCounter ../src/LineCounter.java
Datei: ../src/LineCounter.java hat 30 Zeilen Implementieren Sie die bereits vorhandene Methode `sortFile` der Klasse `FileSort`. Öffnen Sie zuerst die Datei mithilfe von `RandomAccessFile` im Modus `"rw"`. Wandern Sie nun - entsprechend dem Bubblesort-Algorithmus - über die Daten und sortieren Sie die Bytes der Datei. Halten Sie nie mehr als zwei `byte` und die Position als `long` im Speicher. Weitere Variablen können auch noch nötig sein, um den Algorithmus zu implementieren.
```
Testen Sie Ihre Implementierung mit den JUnit-Tests. Die Testdatei für den Unit-Test ist [data.dat](../sources/src/main/resources/pr2/io/random_access/data.dat)
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Zeilen einer Textdatei zählen # Lösung: `RandomAccessFile`
Musterlösung: Musterlösung:
[pr2.io.linecounter](../../solutions/src/main/java/pr2/io/linecounter/) [pr2.io.random_access](../../solutions/src/main/java/pr2/io/random_access/)

View File

@ -1,22 +1,16 @@
# `RandomAccessFile` # `Reader` verwenden
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
`RandomAccessFile` sowohl zum Lesen, als auch zum Schreiben von Daten einsetzen. Verstehen, dass man sich wahlfrei durch die Datei bewegen kann. Textdaten mithilfe von `Reader` verarbeiten.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.random_access](../sources/src/main/java/pr2/io/random_access/). Gehen Sie in das Paket [pr2.io.reader_writer](../sources/src/main/java/pr2/io/reader_writer/).
Bei dieser Aufgabe werden Sie ein Verfahren anwenden, das bei sehr großen Datenmengen zum Einsatz kommt: das Sortieren der Daten direkt auf der Festplatte, ohne sie vollständig in den Hauptspeicher zu laden. Lesen Sie die Datei [kafka.txt](../sources/src/main/resources/pr2/io/reader_writer/kafka.txt) mit einem passenden `Reader` ein und geben Sie sie auf der Konsole aus. Verwenden Sie nicht die `read()`-Methode, die einzelne Zeichen verarbeitet, sondern arbeiten Sie mit einem `char[]`-Buffer.
Implementieren Sie einen [Bubblesort](https://de.wikipedia.org/wiki/Bubblesort) mithilfe von `RandomAccessFile` direkt auf einer Datei. Bubblesort ist ein ausgesprochen ineffizienter Algorithmus (O(n*n)), er ist aber sehr einfach zu implementieren. Da die zu sortierende Datei klein ist, können wir hier mit den Nachteilen von Bubblesort leben.
Implementieren Sie die bereits vorhandene Methode `sortFile` der Klasse `FileSort`. Öffnen Sie zuerst die Datei mithilfe von `RandomAccessFile` im Modus `"rw"`. Wandern Sie nun - entsprechend dem Bubblesort-Algorithmus - über die Daten und sortieren Sie die Bytes der Datei. Halten Sie nie mehr als zwei `byte` und die Position als `long` im Speicher. Weitere Variablen können auch noch nötig sein, um den Algorithmus zu implementieren.
Testen Sie Ihre Implementierung mit den JUnit-Tests. Die Testdatei für den Unit-Test ist [data.dat](../sources/src/main/resources/pr2/io/random_access/data.dat)
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: `RandomAccessFile` # Lösung: `Reader` verwenden
Musterlösung: Musterlösung:
[pr2.io.random_access](../../solutions/src/main/java/pr2/io/random_access/) [pr2.io.reader_writer](../../solutions/src/main/java/pr2/io/reader_writer/)

View File

@ -1,16 +1,26 @@
# `Reader` verwenden # Rot13-Verschlüsselung
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Textdaten mithilfe von `Reader` verarbeiten. Funktionsweise und Einsatz von Filtern.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.reader_writer](../sources/src/main/java/pr2/io/reader_writer/). Gehen Sie in das Paket [pr2.io.rot13](../sources/src/main/java/pr2/io/rot13/).
Lesen Sie die Datei [kafka.txt](../sources/src/main/resources/pr2/io/reader_writer/kafka.txt) mit einem passenden `Reader` ein und geben Sie sie auf der Konsole aus. Verwenden Sie nicht die `read()`-Methode, die einzelne Zeichen verarbeitet, sondern arbeiten Sie mit einem `char[]`-Buffer. Schreiben Sie eine Klasse `Rot13Reader`, die als Filter-Reader implementiert ist und jedes eingelesene Zeichen durch ein Zeichen ersetzt, dessen numerischer Wert um 13 höher ist (d.h. um 13 Schritte im Alphabet verschoben ist).
Schreiben Sie eine Klasse `Rot13`, die einen Dateinamen von der Kommandozeile nimmt und diese Text-Datei mithilfe von `Rot13Reader` liest und auf der Konsole ausgibt.
```console
> cat /tmp/test
DIES IST EIN TEXT, DER GLEICH ROT13 VERSCHLUESSELT WIRD.
> java Rot13 /tmp/test
QVR`-V`a-RV[-aRea9-QR_-TYRVPU-_\a>@-cR_`PUYbR``RYa-dV_Q;
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: `Reader` verwenden # Lösung: Rot13-Verschlüsselung
Musterlösung: Musterlösung:
[pr2.io.reader_writer](../../solutions/src/main/java/pr2/io/reader_writer/) [pr2.io.rot13](../../solutions/src/main/java/pr2/io/rot13/)

View File

@ -1,25 +1,28 @@
# Rot13-Verschlüsselung # Datei zerhacken
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Funktionsweise und Einsatz von Filtern. Daten byteweise aus einem Stream lesen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.rot13](../sources/src/main/java/pr2/io/rot13/). Gehen Sie in das Paket [pr2.io.scrambler](../sources/src/main/java/pr2/io/scrambler/).
Schreiben Sie eine Klasse `Rot13Reader`, die als Filter-Reader implementiert ist und jedes eingelesene Zeichen durch ein Zeichen ersetzt, dessen numerischer Wert um 13 höher ist (d.h. um 13 Schritte im Alphabet verschoben ist). Schreiben Sie eine Klasse `Scrambler`, die einen Dateinamen von der Kommandozeile entgegennimmt, die Datei einliest und dann wieder auf der Konsole ausgibt. Allerdings soll bei der Ausgabe nur jedes zweite Byte berücksichtigt werden.
Schreiben Sie eine Klasse `Rot13`, die einen Dateinamen von der Kommandozeile nimmt und diese Text-Datei mithilfe von `Rot13Reader` liest und auf der Konsole ausgibt.
```console ```console
> cat /tmp/test > java Scrambler ../src/Scrambler.java
DIES IST EIN TEXT, DER GLEICH ROT13 VERSCHLUESSELT WIRD. motjv.oFlIpttem
motjv.oFlNtonEcpin
> java Rot13 /tmp/test motjv.oIEcpin
QVR`-V`a-RV[-aRea9-QR_-TYRVPU-_\a>@-cR_`PUYbR``RYa-dV_Q; pbi ls cabe
pbi ttcvi anSrn[ rs hosIEcpin{ i ag.egh! ){ Sse.r.rnl(
Bteen ae nee"; Sse.xt1; }
ienuSra i;
r
i e ienuSra(rs0)
``` ```

View File

@ -1,5 +1,5 @@
# Lösung: Rot13-Verschlüsselung # Lösung: Datei zerhacken
Musterlösung: Musterlösung:
[pr2.io.rot13](../../solutions/src/main/java/pr2/io/rot13/) [pr2.io.scrambler](../../solutions/src/main/java/pr2/io/scrambler/)

View File

@ -1,29 +1,24 @@
# Datei zerhacken # Serialisierung
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Daten byteweise aus einem Stream lesen. Serialisierung einsetzen können, um Objekte zu persistieren und wieder zu laden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.scrambler](../sources/src/main/java/pr2/io/scrambler/). Gehen Sie in das Paket [pr2.io.serialisierung](../sources/src/main/java/pr2/io/serialisierung/).
Schreiben Sie eine Klasse `Scrambler`, die einen Dateinamen von der Kommandozeile entgegennimmt, die Datei einliest und dann wieder auf der Konsole ausgibt. Allerdings soll bei der Ausgabe nur jedes zweite Byte berücksichtigt werden. In dieser Aufgabe finden Sie bereits eine fertig implementierte Klasse `Board` vor, die ein Schachbrett repräsentiert. Allerdings wird dieses nicht für Schach benutzt, sondern für ein Spiel, bei dem man nur schwarze und weiße Steine auf das Brett stellen kann (z.B. Dame). Die Farbe der Steine wird durch die Enumeration `Color` dargestellt.
```console Was bei dem Schachbrett allerdings noch fehlt, ist eine Möglichkeit den Spielstand zu speichern und später wieder einzulesen.
> java Scrambler ../src/Scrambler.java
motjv.oFlIpttem Schauen Sie sich die Klassen `Board` und `Color` genau an und versuchen Sie diese zu verstehen. Sie können auch testweise ein Brett anlegen und mit Daten befüllen. (Wie dies geht, sehen Sie im JUnit-Test). Die `toString()`-Methode liefert eine anschauliche Darstellung des Spielfeldes.
motjv.oFlNtonEcpin
motjv.oIEcpin Implementieren Sie nun die Methoden `writeToFile` und `loadFromFile` unter Zuhilfenahme von Serialisierung. D.h. anders als in der Aufgabe zu `DataOutputStream`, sollen Sie hier kein eigenes Datenformat implementieren. Verwenden Sie stattdessen einen `ObjectOutputStream` bzw. `ObjectInputStream`.
pbi ls cabe
pbi ttcvi anSrn[ rs hosIEcpin{ i ag.egh! ){ Sse.r.rnl( Lassen Sie den JUnit-Test laufen, um zu sehen, ob die Daten korrekt verarbeitet werden. Die Test-Datei für den Unit-Test ist [testdata.dat](../sources/src/main/resources/pr2/io/serialisierung/testdata.dat)
Bteen ae nee"; Sse.xt1; }
ienuSra i;
r
i e ienuSra(rs0)
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Datei zerhacken # Lösung: Serialisierung
Musterlösung: Musterlösung:
[pr2.io.scrambler](../../solutions/src/main/java/pr2/io/scrambler/) [pr2.io.serialisierung](../../solutions/src/main/java/pr2/io/serialisierung/)

View File

@ -1,24 +1,22 @@
# Serialisierung # Einen generischen Typ schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Serialisierung einsetzen können, um Objekte zu persistieren und wieder zu laden. Einen vorhandenen Typ so umgestalten, dass er als generischer Typ verwendet werden kann.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.io.serialisierung](../sources/src/main/java/pr2/io/serialisierung/). Gehen Sie in das Paket [pr2.generics.einfach](../sources/src/main/java/pr2/generics/einfach/).
In dieser Aufgabe finden Sie bereits eine fertig implementierte Klasse `Board` vor, die ein Schachbrett repräsentiert. Allerdings wird dieses nicht für Schach benutzt, sondern für ein Spiel, bei dem man nur schwarze und weiße Steine auf das Brett stellen kann (z.B. Dame). Die Farbe der Steine wird durch die Enumeration `Color` dargestellt. Sie finden mit `Liste` eine sehr simple Implementierung einer einfach verketteten Liste vor. Zusätzlich gib es auch noch Tests, die die Liste testen.
Was bei dem Schachbrett allerdings noch fehlt, ist eine Möglichkeit den Spielstand zu speichern und später wieder einzulesen. Führen Sie die Tests aus und überzeugen Sie sich, dass die Liste korrekt funktioniert.
Schauen Sie sich die Klassen `Board` und `Color` genau an und versuchen Sie diese zu verstehen. Sie können auch testweise ein Brett anlegen und mit Daten befüllen. (Wie dies geht, sehen Sie im JUnit-Test). Die `toString()`-Methode liefert eine anschauliche Darstellung des Spielfeldes. Schreiben Sie die Klasse `Liste` so um, dass sie zu einem generischen Typ wird. Dies bedeutet insbesondere, dass die Methoden `get` und `add` nicht mehr mit `Object` arbeiten, sondern typsicher werden. Sie dürfen in Ihrer Lösung __keine Casts__ verwenden, d.h. Sie müssen sich auch mit der Klasse `ListNode` beschäftigen und hier Änderungen vornehmen.
Implementieren Sie nun die Methoden `writeToFile` und `loadFromFile` unter Zuhilfenahme von Serialisierung. D.h. anders als in der Aufgabe zu `DataOutputStream`, sollen Sie hier kein eigenes Datenformat implementieren. Verwenden Sie stattdessen einen `ObjectOutputStream` bzw. `ObjectInputStream`. Führen Sie die Tests erneut aus, um sicherzugehen, dass Sie bei Ihren Änderungen nichts kaputt gemacht haben.
Lassen Sie den JUnit-Test laufen, um zu sehen, ob die Daten korrekt verarbeitet werden. Die Test-Datei für den Unit-Test ist [testdata.dat](../sources/src/main/resources/pr2/io/serialisierung/testdata.dat)
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Serialisierung # Lösung: Einen generischen Typ schreiben
Musterlösung: Musterlösung:
[pr2.io.serialisierung](../../solutions/src/main/java/pr2/io/serialisierung/) [pr2.generics.einfach](../../solutions/src/main/java/pr2/generics/einfach/)

View File

@ -1,22 +1,18 @@
# Einen generischen Typ schreiben # Generische Klasse Pair schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen vorhandenen Typ so umgestalten, dass er als generischer Typ verwendet werden kann. Von einem generischen Typ erben.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.einfach](../sources/src/main/java/pr2/generics/einfach/). Gehen Sie in das Paket [pr2.generics.pair](../sources/src/main/java/pr2/generics/pair/).
Sie finden mit `Liste` eine sehr simple Implementierung einer einfach verketteten Liste vor. Zusätzlich gib es auch noch Tests, die die Liste testen. Schreiben Sie eine generische Klasse `Pair`, die zwei Objekte unterschiedlichen Typs verwalten kann. Die Instanzen von `Pair` sollen unveränderlich (**immutable**) sein.
Führen Sie die Tests aus und überzeugen Sie sich, dass die Liste korrekt funktioniert. Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse.
Schreiben Sie die Klasse `Liste` so um, dass sie zu einem generischen Typ wird. Dies bedeutet insbesondere, dass die Methoden `get` und `add` nicht mehr mit `Object` arbeiten, sondern typsicher werden. Sie dürfen in Ihrer Lösung __keine Casts__ verwenden, d.h. Sie müssen sich auch mit der Klasse `ListNode` beschäftigen und hier Änderungen vornehmen.
Führen Sie die Tests erneut aus, um sicherzugehen, dass Sie bei Ihren Änderungen nichts kaputt gemacht haben.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Einen generischen Typ schreiben # Lösung: Generische Klasse Pair schreiben
Musterlösung: Musterlösung:
[pr2.generics.einfach](../../solutions/src/main/java/pr2/generics/einfach/) [pr2.generics.pair](../../solutions/src/main/java/pr2/generics/pair/)

View File

@ -1,4 +1,4 @@
# Generische Klasse Pair schreiben # Generische Klasse Pair erweitern: NumberPair
[Musterlösung](solution/) [Musterlösung](solution/)
@ -8,9 +8,9 @@ Von einem generischen Typ erben.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.pair](../sources/src/main/java/pr2/generics/pair/). Gehen Sie in das Paket [pr2.generics.number_pair](../sources/src/main/java/pr2/generics/number_pair/).
Schreiben Sie eine generische Klasse `Pair`, die zwei Objekte unterschiedlichen Typs verwalten kann. Die Instanzen von `Pair` sollen unveränderlich (**immutable**) sein. Schreiben Sie eine generische Klasse `NumberPair`, die von der Klasse `Pair` aus der vorhergehenden Aufgabe abgeleitet ist und erzwingt, dass beide verwaltete Objekte von `Number` oder einer Subklasse von `Number` (`Double`, `Integer`, `Long` etc.) sind.
Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse. Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse.

View File

@ -1,5 +1,5 @@
# Lösung: Generische Klasse Pair schreiben # Lösung: Generische Klasse Pair erweitern: NumberPair
Musterlösung: Musterlösung:
[pr2.generics.pair](../../solutions/src/main/java/pr2/generics/pair/) [pr2.generics.number_pair](../../solutions/src/main/java/pr2/generics/number_pair/)

View File

@ -1,4 +1,4 @@
# Generische Klasse Pair erweitern: NumberPair # Generische Klasse Pair erweitern: SamePair
[Musterlösung](solution/) [Musterlösung](solution/)
@ -8,9 +8,9 @@ Von einem generischen Typ erben.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.number_pair](../sources/src/main/java/pr2/generics/number_pair/). Gehen Sie in das Paket [pr2.generics.same_pair](../sources/src/main/java/pr2/generics/same_pair/).
Schreiben Sie eine generische Klasse `NumberPair`, die von der Klasse `Pair` aus der vorhergehenden Aufgabe abgeleitet ist und erzwingt, dass beide verwaltete Objekte von `Number` oder einer Subklasse von `Number` (`Double`, `Integer`, `Long` etc.) sind. Schreiben Sie eine generische Klasse `SamePair`, die von der Klasse `Pair` aus der vorhergehenden Aufgabe abgeleitet ist und erzwingt, dass beide verwaltete Objekte vom selben Typ sind.
Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse. Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse.

View File

@ -1,5 +1,5 @@
# Lösung: Generische Klasse Pair erweitern: NumberPair # Lösung: Generische Klasse Pair erweitern: SamePair
Musterlösung: Musterlösung:
[pr2.generics.number_pair](../../solutions/src/main/java/pr2/generics/number_pair/) [pr2.generics.same_pair](../../solutions/src/main/java/pr2/generics/same_pair/)

View File

@ -1,16 +1,16 @@
# Generische Klasse Pair erweitern: SamePair # PairList
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Von einem generischen Typ erben. Sammlungen von Objekten eines generischen Typs erstellen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.same_pair](../sources/src/main/java/pr2/generics/same_pair/). Gehen Sie in das Paket [pr2.generics.pairlist](../sources/src/main/java/pr2/generics/pairlist/).
Schreiben Sie eine generische Klasse `SamePair`, die von der Klasse `Pair` aus der vorhergehenden Aufgabe abgeleitet ist und erzwingt, dass beide verwaltete Objekte vom selben Typ sind. Schreiben Sie eine generische Klasse `PairList`, die eine beliebige Anzahl von `Pair`-Objekten verwalten kann. Die Anzahl der maximal gespeicherten Objekte wird beim Erzeugen mitgegeben. Die Klasse erlaubt das Hinzufügen (`add`) und das Auslesen von Objekten anhand des Indexes (`get`).
Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse. Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse.

View File

@ -1,5 +1,5 @@
# Lösung: Generische Klasse Pair erweitern: SamePair # Lösung: PairList
Musterlösung: Musterlösung:
[pr2.generics.same_pair](../../solutions/src/main/java/pr2/generics/same_pair/) [pr2.generics.pairlist](../../solutions/src/main/java/pr2/generics/pairlist/)

View File

@ -1,18 +1,16 @@
# PairList # Wildcard benutzen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Sammlungen von Objekten eines generischen Typs erstellen. Wildcards einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.pairlist](../sources/src/main/java/pr2/generics/pairlist/). Gehen Sie in das Paket [pr2.generics.printer](../sources/src/main/java/pr2/generics/printer/).
Schreiben Sie eine generische Klasse `PairList`, die eine beliebige Anzahl von `Pair`-Objekten verwalten kann. Die Anzahl der maximal gespeicherten Objekte wird beim Erzeugen mitgegeben. Die Klasse erlaubt das Hinzufügen (`add`) und das Auslesen von Objekten anhand des Indexes (`get`). Schreiben Sie eine Klasse `CollectionPrinter` mit einer statischen Methode `print`, der man eine beliebige (generische) Collection übergeben kann und die dann deren Inhalt ausdruckt. Eine _Collection_ ist eine Klasse, die beliebig viele Objekte verwalten kann und über die man mit der _for each_-Schleife iterieren kann.
Testen Sie Ihre Implementierung mit der vorhandenen `Main`-Klasse.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: PairList # Lösung: Wildcard benutzen
Musterlösung: Musterlösung:
[pr2.generics.pairlist](../../solutions/src/main/java/pr2/generics/pairlist/) [pr2.generics.printer](../../solutions/src/main/java/pr2/generics/printer/)

View File

@ -1,16 +1,20 @@
# Wildcard benutzen # Generische Queue
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Wildcards einsetzen. Einen komplexeren generischen Typ entwickeln.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.printer](../sources/src/main/java/pr2/generics/printer/). Gehen Sie in das Paket [pr2.generics.queue](../sources/src/main/java/pr2/generics/queue/).
Schreiben Sie eine Klasse `CollectionPrinter` mit einer statischen Methode `print`, der man eine beliebige (generische) Collection übergeben kann und die dann deren Inhalt ausdruckt. Eine _Collection_ ist eine Klasse, die beliebig viele Objekte verwalten kann und über die man mit der _for each_-Schleife iterieren kann. Schreiben Sie eine generische Klasse `Queue`, die eine einfache Warteschlange (Queue) realisiert. Über die Methode `offer` können Objekte hinzugefügt werden, über `poll` wieder ausgelesen. Über Probleme des Over- und Underflows brauchen Sie sich hier keine Gedanken zu machen.
Erweitern Sie die Klasse `Queue` um eine Methode `addAll`, der man eine andere `Queue` übergibt und die dann alle Elemente der übergebenen Queue in die aktuelle übernimmt.
Erweitern Sie die Klasse `Queue` aus der vorhergehenden Aufgabe um eine Methode `copyInto`, der man eine andere `Queue` übergibt und die dann alle Elemente der aktuellen Queue in die übergebenen kopiert.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Wildcard benutzen # Lösung: Generische Queue
Musterlösung: Musterlösung:
[pr2.generics.printer](../../solutions/src/main/java/pr2/generics/printer/) [pr2.generics.queue](../../solutions/src/main/java/pr2/generics/queue/)

View File

@ -1,20 +1,25 @@
# Generische Queue # `super` und `extends` einsetzen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen komplexeren generischen Typ entwickeln. Methoden unter Verwendung von `super` und `extends` gestalten, sodass sie flexibel auch mit Sub- bzw. Supertypen umgehen können.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.queue](../sources/src/main/java/pr2/generics/queue/). Gehen Sie in das Paket [pr2.generics.super_extends](../sources/src/main/java/pr2/generics/super_extends/).
Schreiben Sie eine generische Klasse `Queue`, die eine einfache Warteschlange (Queue) realisiert. Über die Methode `offer` können Objekte hinzugefügt werden, über `poll` wieder ausgelesen. Über Probleme des Over- und Underflows brauchen Sie sich hier keine Gedanken zu machen. In dieser Aufgabe sollen Sie die Klasse `Liste` erweitern.
Erweitern Sie die Klasse `Queue` um eine Methode `addAll`, der man eine andere `Queue` übergibt und die dann alle Elemente der übergebenen Queue in die aktuelle übernimmt. Fügen Sie `Liste` zwei Methoden hinzu:
Erweitern Sie die Klasse `Queue` aus der vorhergehenden Aufgabe um eine Methode `copyInto`, der man eine andere `Queue` übergibt und die dann alle Elemente der aktuellen Queue in die übergebenen kopiert. * `fillFrom`: befüllt die Liste mit den Daten aus einer anderen (übergebene) Liste.
* `copyInto`: kopiert die Daten der Liste in eine andere (übergebene) Liste.
Verwenden Sie für Ihre Lösung `super` und `extends` zusammen mit Wildcards (`?`).
Kommentieren Sie die Testmethode in den vorhandenen Tests ein und führen Sie diese danach aus. Versichern Sie sich, dass Ihre Implementierung korrekt funktioniert, bevor Sie die Lösung abgeben.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Generische Queue # Lösung: `super` und `extends` einsetzen
Musterlösung: Musterlösung:
[pr2.generics.queue](../../solutions/src/main/java/pr2/generics/queue/) [pr2.generics.super_extends](../../solutions/src/main/java/pr2/generics/super_extends/)

View File

@ -1,25 +1,39 @@
# `super` und `extends` einsetzen # Generische Typen zusammen mit Wildcards einsetzen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Methoden unter Verwendung von `super` und `extends` gestalten, sodass sie flexibel auch mit Sub- bzw. Supertypen umgehen können. Gebundene und ungebundene Wildcards einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.super_extends](../sources/src/main/java/pr2/generics/super_extends/). Gehen Sie in das Paket [pr2.generics.wildcards](../sources/src/main/java/pr2/generics/wildcards/).
In dieser Aufgabe sollen Sie die Klasse `Liste` erweitern. In dieser Aufgabe finden Sie bereits eine Implementierung einer generischen, auf Arrays basierenden Liste namens `SimpleList` vor. An dieser müssen Sie nichts verändern, sondern verwenden die Klasse wie sie ist.
Fügen Sie `Liste` zwei Methoden hinzu: Schreiben Sie nun eine _nicht generische_ Klasse `ListHelper`, die zwei statische Methoden enthält:
* `fillFrom`: befüllt die Liste mit den Daten aus einer anderen (übergebene) Liste. * `printList`: Diese Methode bekommt eine beliebige `SimpleList` übergeben und druckt deren Inhalt einfach auf der Konsole aus. Deswegen hat die Methode auch den Rückgabetyp `void`.
* `copyInto`: kopiert die Daten der Liste in eine andere (übergebene) Liste. * `sumList`: Diese Methode nimmt als Parameter `SimpleList`-Objekte, die irgendeine Form von Zahlen enthalten (`Number` oder Subklassen davon) und berechnet deren Summe. Das Ergebnis wird als `double`-Wert zurückgegeben.
Verwenden Sie für Ihre Lösung `super` und `extends` zusammen mit Wildcards (`?`). Verwenden Sie für die Methoden gebundene bzw. ungebundene Wildcards.
Kommentieren Sie die Testmethode in den vorhandenen Tests ein und führen Sie diese danach aus. Versichern Sie sich, dass Ihre Implementierung korrekt funktioniert, bevor Sie die Lösung abgeben. Kommentieren Sie die entsprechenden Zeilen in der Klasse `Main` aus und sehen überprüfen Sie, ob Ihre Implementierungen auch wie gewünscht funktionieren. Die Ausgabe sollte sein:
```console
Dies
ist
ein
Test
.
1
2
3
4
5
15.0
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: `super` und `extends` einsetzen # Lösung: Generische Typen zusammen mit Wildcards einsetzen
Musterlösung: Musterlösung:
[pr2.generics.super_extends](../../solutions/src/main/java/pr2/generics/super_extends/) [pr2.generics.wildcards](../../solutions/src/main/java/pr2/generics/wildcards/).

View File

@ -1,22 +1,16 @@
# Generischen Typ verwenden # Eigene compare-Methode schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Einen vorgegebenen generischen Typ einsetzen, um typsicher eine Menge von Objekten zu verwalten. Objekte vergleichen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.verwenden](../sources/src/main/java/pr2/generics/verwenden/). Gehen Sie in das Paket [pr2.lambda.array_sorter](../sources/src/main/java/pr2/lambda/array_sorter/).
In dieser Aufgabe werden Sie ein einfaches Spiel implementieren, mit bei dem man einen Stapel Münzen möglichst schnell abräumen muss. Man nimmt eine Münze, indem man auf sie klickt. Jede Münze gibt dieselbe Anzahl von Punkten. Es geht also eher um das schnelle Klicken. Schreiben Sie ein Java-Programm `ReverseSort`, das ein Array mit `Date`-Objekten erzeugt und dieses dann mithilfe der `Arrays.sort`-Methode in umgekehrter Reihenfolge sortiert. Um die umgekehrte Sortierung zu erhalten, erzeugen Sie bitte direkt im Aufruf der `sort`-Methode einen entsprechenden `Comparator` als anonyme innere Klasse.
Die Münzen liegen als Stapel (_Stack_) vor, d.h. man kann immer nur die oberste Münze herunternehmen. Um dies in dem Spiel zu realisieren, sollen Sie den vorgefertigten, generischen Datentyp `Stack` verwenden, den Sie im Paket `java.util` finden.
Bei dieser Aufgabe sollen Sie _nicht_ die Klasse `GameBoard` generisch machen, sondern innerhalb der Klasse den `Stack` als generischen Typ verwenden.
Öffnen Sie die Klasse `GameBoard` und orientieren Sie sich bei Ihren Änderungen an den `TODO`-Kommentaren.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Generischen Typ verwenden # Lösung: Eigene compare-Methode schreiben
Musterlösung: Musterlösung:
[pr2.generics.verwenden](../../solutions/src/main/java/pr2/generics/verwenden/). [pr2.lambda.array_sorter](../../solutions/src/main/java/pr2/lambda/array_sorter/)

View File

@ -1,39 +1,20 @@
# Generische Typen zusammen mit Wildcards einsetzen # Innere Klasse Beobachter
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Gebundene und ungebundene Wildcards einsetzen. Zugriff von inneren Klassen auf die umgebende Klasse.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.generics.wildcards](../sources/src/main/java/pr2/generics/wildcards/). Gehen Sie in das Paket: [pr2.lambda.observer](../sources/src/main/java/pr2/lambda/observer/).
In dieser Aufgabe finden Sie bereits eine Implementierung einer generischen, auf Arrays basierenden Liste namens `SimpleList` vor. An dieser müssen Sie nichts verändern, sondern verwenden die Klasse wie sie ist. Dort finden Sie das Interface `Beobachter`.
Schreiben Sie nun eine _nicht generische_ Klasse `ListHelper`, die zwei statische Methoden enthält: Schreiben Sie eine Klasse `Datenhalter`, die eine einziges, privates Attribut vom Typ `int` enthält. Setzen Sie das Attribut im Konstruktor, erzeugen Sie aber keinen Getter.
* `printList`: Diese Methode bekommt eine beliebige `SimpleList` übergeben und druckt deren Inhalt einfach auf der Konsole aus. Deswegen hat die Methode auch den Rückgabetyp `void`. Implementieren Sie das Interface `Beobachter` als nicht-statische, private innere Klasse in `Datenhalter` und erlauben Sie über den Beobachter Zugriff auf das Attribut, indem Sie ein entsprechendes Objekt vom Typ `Beobachter` zurückgeben. Testen Sie Ihre Implementierung mit einem JUnit-Test.
* `sumList`: Diese Methode nimmt als Parameter `SimpleList`-Objekte, die irgendeine Form von Zahlen enthalten (`Number` oder Subklassen davon) und berechnet deren Summe. Das Ergebnis wird als `double`-Wert zurückgegeben.
Verwenden Sie für die Methoden gebundene bzw. ungebundene Wildcards.
Kommentieren Sie die entsprechenden Zeilen in der Klasse `Main` aus und sehen überprüfen Sie, ob Ihre Implementierungen auch wie gewünscht funktionieren. Die Ausgabe sollte sein:
```console
Dies
ist
ein
Test
.
1
2
3
4
5
15.0
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Generische Typen zusammen mit Wildcards einsetzen # Lösung: Innere Klasse Beobachter
Musterlösung: Musterlösung:
[pr2.generics.wildcards](../../solutions/src/main/java/pr2/generics/wildcards/). [pr2.lambda.observer](../../solutions/src/main/java/pr2/lambda/observer/).

View File

@ -1,16 +1,20 @@
# Eigene compare-Methode schreiben # Callback mit anonymer Klasse realisieren
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Objekte vergleichen. Eine gegebene Funktion durch einen Callback parametrieren. Der Callback wird als anonyme innere Klasse realisiert.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.array_sorter](../sources/src/main/java/pr2/lambda/array_sorter/). Gehen Sie in das Paket [pr2.lambda.callback](../sources/src/main/java/pr2/lambda/callback/).
Schreiben Sie ein Java-Programm `ReverseSort`, das ein Array mit `Date`-Objekten erzeugt und dieses dann mithilfe der `Arrays.sort`-Methode in umgekehrter Reihenfolge sortiert. Um die umgekehrte Sortierung zu erhalten, erzeugen Sie bitte direkt im Aufruf der `sort`-Methode einen entsprechenden `Comparator` als anonyme innere Klasse. In dieser Aufgabe wird ein sehr gängiges Muster benutzt, dass auch bei großen Suchmaschinen zum Einsatz kommt. Über eine Filter-Funktion werden aus einer Menge von Daten diejenigen ausgewählt, die gewünscht sind. Die Auswahlfunktion wird von außen vorgegeben, sodass beliebige Filteroperationen möglich sind, auch solche, die beim Schreiben des Rahmenwerkes noch nicht bekannt waren.
Sehen Sie sich das Interface `Prediacte` und die Klasse `NumberSelector` an und versuchen Sie die Funktionsweise der beiden zu verstehen. Betrachten Sie nun die Klasse `Main`, die versucht zuerst die geraden und dann die ungeraden Zahlen auszuwählen und auszugeben. Der hierfür nötige Code ist zwar schon weitgehend vorhanden, aber in der `main`-Methode müssen Sie noch zwei passende Filterfunktionen als **anonyme innere Klassen** realisieren.
Nachdem Sie die beiden Filter geschrieben haben, lassen Sie das Programm laufen und überprüfen Sie, ob wirklich die richtigen Zahlen ausgewählt werden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Eigene compare-Methode schreiben # Lösung: Callback mit anonymer Klasse realisieren
Musterlösung: Musterlösung:
[pr2.lambda.array_sorter](../../solutions/src/main/java/pr2/lambda/array_sorter/) [pr2.lambda.callback](../../solutions/src/main/java/pr2/lambda/callback/)

View File

@ -1,20 +1,19 @@
# Innere Klasse Beobachter # Comparator als Lambda
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Zugriff von inneren Klassen auf die umgebende Klasse. Lambdas verwenden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket: [pr2.lambda.observer](../sources/src/main/java/pr2/lambda/observer/). Gehen Sie in das Paket
[pr2.lambda.comparator](../sources/src/main/java/pr2/lambda/comparator/).
Dort finden Sie das Interface `Beobachter`. Als Teil der Java-Klassenbibliothek findet sich das Interface `Comparator`, mit dem beim Sortieren eine Sortierreihenfolge vorgeben werden kann. Da es sich um ein funktionales Interface handelt, kann man es auch mit einem Lambda-Ausdruck implementieren. Schauen Sie sich den Aufbau des Interfaces in der JavaDoc an.
Schreiben Sie eine Klasse `Datenhalter`, die eine einziges, privates Attribut vom Typ `int` enthält. Setzen Sie das Attribut im Konstruktor, erzeugen Sie aber keinen Getter. Sortieren Sie ein Array von Zahlen (repräsentiert als `Integer`, nicht als `int`) in _absteigender_ Reihenfolge mithilfe der Methode `sort` der Klasse `Arrays` und geben Sie ihr einen entsprechenden `Comparator` als Lambda-Ausdruck mit.
Implementieren Sie das Interface `Beobachter` als nicht-statische, private innere Klasse in `Datenhalter` und erlauben Sie über den Beobachter Zugriff auf das Attribut, indem Sie ein entsprechendes Objekt vom Typ `Beobachter` zurückgeben. Testen Sie Ihre Implementierung mit einem JUnit-Test.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Innere Klasse Beobachter # Lösung: Comparator als Lambda
Musterlösung: Musterlösung:
[pr2.lambda.observer](../../solutions/src/main/java/pr2/lambda/observer/). [pr2.lambda.comparator](../../solutions/src/main/java/pr2/lambda/comparator/)

View File

@ -1,21 +1,23 @@
# Callback mit anonymer Klasse realisieren # Callback mit Lambda realisieren
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Eine gegebene Funktion durch einen Callback parametrieren. Der Callback wird als anonyme innere Klasse realisiert. Eine gegebene Funktion durch einen Callback parametrieren. Der Callback wird als Lambda realisiert.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.callback](../sources/src/main/java/pr2/lambda/callback/). Gehen Sie in das Paket [pr2.lambda.lambdas](../sources/src/main/java/pr2/lambda/lambdas/).
In dieser Aufgabe wird ein sehr gängiges Muster benutzt, dass auch bei großen Suchmaschinen zum Einsatz kommt. Über eine Filter-Funktion werden aus einer Menge von Daten diejenigen ausgewählt, die gewünscht sind. Die Auswahlfunktion wird von außen vorgegeben, sodass beliebige Filteroperationen möglich sind, auch solche, die beim Schreiben des Rahmenwerkes noch nicht bekannt waren. In dieser Aufgabe wird ein sehr gängiges Muster benutzt, dass auch bei großen Suchmaschinen zum Einsatz kommt. Über eine Filter-Funktion werden aus einer Menge von Daten diejenigen ausgewählt, die gewünscht sind. Die Auswahlfunktion wird von außen vorgegeben, sodass beliebige Filteroperationen möglich sind, auch solche, die beim Schreiben des Rahmenwerkes noch nicht bekannt waren.
Sehen Sie sich das Interface `Prediacte` und die Klasse `NumberSelector` an und versuchen Sie die Funktionsweise der beiden zu verstehen. Betrachten Sie nun die Klasse `Main`, die versucht zuerst die geraden und dann die ungeraden Zahlen auszuwählen und auszugeben. Der hierfür nötige Code ist zwar schon weitgehend vorhanden, aber in der `main`-Methode müssen Sie noch zwei passende Filterfunktionen als **anonyme innere Klassen** realisieren. Sehen Sie sich das Interface `Predicate` und die Klasse `NumberSelector` an und versuchen Sie die Funktionsweise der beiden zu verstehen. Betrachten Sie nun die Klasse `Main`, die versucht zuerst die geraden und dann die ungeraden Zahlen auszuwählen und auszugeben. Der hierfür nötige Code ist zwar schon weitgehend vorhanden, aber in der `main`-Methode müssen Sie noch zwei passende Filterfunktionen als **Lambda** realisieren.
Nachdem Sie die beiden Filter geschrieben haben, lassen Sie das Programm laufen und überprüfen Sie, ob wirklich die richtigen Zahlen ausgewählt werden. Nachdem Sie die beiden Filter geschrieben haben, lassen Sie das Programm laufen und überprüfen Sie, ob wirklich die richtigen Zahlen ausgewählt werden.
Vergleichen Sie die Lösung mit Lambdas mit der aus der vorhergehenden Aufgabe, die auf anonymen inneren Klassen basiert hat.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Callback mit anonymer Klasse realisieren # Lösung: Callback mit Lambda realisieren
Musterlösung: Musterlösung:
[pr2.lambda.callback](../../solutions/src/main/java/pr2/lambda/callback/) [pr2.lambda.lambdas](../../solutions/src/main/java/pr2/lambda/lambdas/)

View File

@ -1,19 +1,18 @@
# Comparator als Lambda # MatrixSuche
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Lambdas verwenden. Statische innere Klassen einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket Gehen Sie in das Paket [pr2.lambda.matrixsuche](../sources/src/main/java/pr2/lambda/matrixsuche/).
[pr2.lambda.comparator](../sources/src/main/java/pr2/lambda/comparator/).
Als Teil der Java-Klassenbibliothek findet sich das Interface `Comparator`, mit dem beim Sortieren eine Sortierreihenfolge vorgeben werden kann. Da es sich um ein funktionales Interface handelt, kann man es auch mit einem Lambda-Ausdruck implementieren. Schauen Sie sich den Aufbau des Interfaces in der JavaDoc an. Schreiben Sie eine Klasse `MatrixSuche`, die eine statische Methode `findEntry` anbietet. Die Methode soll in einem zweidimensionalen `int`-Array nach einem gegebenen Eintrag suchen und die Position des gefundenen Eintrags in der Matrix zurückgeben. Um die Position zurückzugeben, verwenden Sie bitte eine statische innere Klasse namens `Position`, die die x- und y-Postion enthält.
Sortieren Sie ein Array von Zahlen (repräsentiert als `Integer`, nicht als `int`) in _absteigender_ Reihenfolge mithilfe der Methode `sort` der Klasse `Arrays` und geben Sie ihr einen entsprechenden `Comparator` als Lambda-Ausdruck mit. Überschreiben Sie die `toString`-Methode in `Position` und testen Sie, ob Ihre Implementierung richtig funktioniert.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Comparator als Lambda # Lösung: MatrixSuche
Musterlösung: Musterlösung:
[pr2.lambda.comparator](../../solutions/src/main/java/pr2/lambda/comparator/) [pr2.lambda.matrixsuche](../../solutions/src/main/java/pr2/lambda/matrixsuche/)

View File

@ -1,22 +1,24 @@
# Callback mit Lambda realisieren # StringTransmogrifier
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Eine gegebene Funktion durch einen Callback parametrieren. Der Callback wird als Lambda realisiert. Funktionale Interfaces entwerfen und verwenden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.lambdas](../sources/src/main/java/pr2/lambda/lambdas/). Gehen Sie in das Paket [pr2.lambda.mogrifier_1](../sources/src/main/java/pr2/lambda/mogrifier_1/).
In dieser Aufgabe wird ein sehr gängiges Muster benutzt, dass auch bei großen Suchmaschinen zum Einsatz kommt. Über eine Filter-Funktion werden aus einer Menge von Daten diejenigen ausgewählt, die gewünscht sind. Die Auswahlfunktion wird von außen vorgegeben, sodass beliebige Filteroperationen möglich sind, auch solche, die beim Schreiben des Rahmenwerkes noch nicht bekannt waren. Schreiben Sie ein funktionales Interface namens `StringFunction`. Die Methode des Interfaces nimmt eine String und gibt einen String zurück.
Sehen Sie sich das Interface `Predicate` und die Klasse `NumberSelector` an und versuchen Sie die Funktionsweise der beiden zu verstehen. Betrachten Sie nun die Klasse `Main`, die versucht zuerst die geraden und dann die ungeraden Zahlen auszuwählen und auszugeben. Der hierfür nötige Code ist zwar schon weitgehend vorhanden, aber in der `main`-Methode müssen Sie noch zwei passende Filterfunktionen als **Lambda** realisieren. Schreiben Sie eine Klasse `StringTransmogrifier`, die eine statische Methode `transmogrify` hat, der man ein String-Array und eine `StringFunction` übergibt. Die Methode wendet die Funktion auf jedes Element des Arrays an und gibt ein neues Array mit dem Ergebnis zurück.
Nachdem Sie die beiden Filter geschrieben haben, lassen Sie das Programm laufen und überprüfen Sie, ob wirklich die richtigen Zahlen ausgewählt werden. Schreiben Sie eine Klasse `StringTransmogrifierTest`, die ein String-Array erzeugt und dann mithilfe der Klasse `StringTransmogrifier` die Elemente verändert. Nehmen Sie folgende Änderungen am Array vor, indem Sie entsprechende Lambda-Ausdrücke oder Methodenreferenzen übergeben:
Vergleichen Sie die Lösung mit Lambdas mit der aus der vorhergehenden Aufgabe, die auf anonymen inneren Klassen basiert hat. * Umwandeln aller Buchstaben in Kleinbuchstaben.
* Umwandeln aller Buchstaben in Großbuchstaben.
* Ersetzen jedes Buchstaben durch den im Alphabet folgenden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Callback mit Lambda realisieren # Lösung: StringTransmogrifier
Musterlösung: Musterlösung:
[pr2.lambda.lambdas](../../solutions/src/main/java/pr2/lambda/lambdas/) [pr2.lambda.mogrifier_1](../../solutions/src/main/java/pr2/lambda/mogrifier_1/)

View File

@ -1,18 +1,18 @@
# MatrixSuche # StringTransmogrifier erweitern
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Statische innere Klassen einsetzen. Funktionale Interfaces entwerfen und verwenden.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.matrixsuche](../sources/src/main/java/pr2/lambda/matrixsuche/). Gehen Sie in das Paket [pr2.lambda.mogrifier_2](../sources/src/main/java/pr2/lambda/mogrifier_2/).
Schreiben Sie eine Klasse `MatrixSuche`, die eine statische Methode `findEntry` anbietet. Die Methode soll in einem zweidimensionalen `int`-Array nach einem gegebenen Eintrag suchen und die Position des gefundenen Eintrags in der Matrix zurückgeben. Um die Position zurückzugeben, verwenden Sie bitte eine statische innere Klasse namens `Position`, die die x- und y-Postion enthält. Ausgehend von der vorhergehenden Aufgabe, erweitern Sie das Interface `StringFunction` um eine _statische Methode_ namens `caesar`, mit der man sich eine `StringFunction` erzeugen lassen kann, die die Buchstaben des Strings um einen frei wählbaren Wert verschiebt.
Überschreiben Sie die `toString`-Methode in `Position` und testen Sie, ob Ihre Implementierung richtig funktioniert. Teste Sie Ihre Implementierung wieder mit `StringTransmogrifierTest`.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: MatrixSuche # Lösung: StringTransmogrifier erweitern
Musterlösung: Musterlösung:
[pr2.lambda.matrixsuche](../../solutions/src/main/java/pr2/lambda/matrixsuche/) [pr2.lambda.mogrifier_2](../../solutions/src/main/java/pr2/lambda/mogrifier_2/)

View File

@ -1,24 +1,20 @@
# StringTransmogrifier # Iterator schreiben
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Funktionale Interfaces entwerfen und verwenden. Für eine gegebene Klasse einen Iterator schreiben.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.mogrifier_1](../sources/src/main/java/pr2/lambda/mogrifier_1/). Gehen Sie in das Paket [pr2.collections.iterator](../sources/src/main/java/pr2/collections/iterator/).
Schreiben Sie ein funktionales Interface namens `StringFunction`. Die Methode des Interfaces nimmt eine String und gibt einen String zurück. In dieser Aufgabe sollen Sie für eine bereits vorhandene Klasse einen Iterator schreiben. Bei dieser Klasse (`SimpleStack`) handelt es sich um einen sehr einfach (und nicht sehr sicher) programmierten Stack.
Schreiben Sie eine Klasse `StringTransmogrifier`, die eine statische Methode `transmogrify` hat, der man ein String-Array und eine `StringFunction` übergibt. Die Methode wendet die Funktion auf jedes Element des Arrays an und gibt ein neues Array mit dem Ergebnis zurück. Implementieren Sie in `SimpleStack<T>` das Interface `Iterable<T>` und schreiben Sie, wie vom Interface verlangt einen Iterator für die Klasse. Sie sollten hier innere Klasse verwenden, um den Zugriff auf die privaten Attribute von `SimpleStack` zu vereinfachen.
Schreiben Sie eine Klasse `StringTransmogrifierTest`, die ein String-Array erzeugt und dann mithilfe der Klasse `StringTransmogrifier` die Elemente verändert. Nehmen Sie folgende Änderungen am Array vor, indem Sie entsprechende Lambda-Ausdrücke oder Methodenreferenzen übergeben: Benutzen Sie die Tests in `SimpleStackTest`, um zu überprüfen, dass Ihre Implementierung des Iterators richtig funktioniert. Hierzu müssen Sie die entsprechenden Tests allerdings erst einkommentieren.
* Umwandeln aller Buchstaben in Kleinbuchstaben.
* Umwandeln aller Buchstaben in Großbuchstaben.
* Ersetzen jedes Buchstaben durch den im Alphabet folgenden.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: StringTransmogrifier # Lösung: Iterator schreiben
Musterlösung: Musterlösung:
[pr2.lambda.mogrifier_1](../../solutions/src/main/java/pr2/lambda/mogrifier_1/) [pr2.collections.iterator](../../solutions/src/main/java/pr2/collections/iterator/)

View File

@ -1,18 +1,16 @@
# StringTransmogrifier erweitern # Iterator programmieren
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Funktionale Interfaces entwerfen und verwenden. Iteratoren verstehen und programmieren.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.mogrifier_2](../sources/src/main/java/pr2/lambda/mogrifier_2/). Im Paket [pr2.collections.list_iterator](../sources/src/main/java/pr2/collections/list_iterator/) finden Sie den Code für eine einfach verkettete Liste `Liste<T>`.
Ausgehend von der vorhergehenden Aufgabe, erweitern Sie das Interface `StringFunction` um eine _statische Methode_ namens `caesar`, mit der man sich eine `StringFunction` erzeugen lassen kann, die die Buchstaben des Strings um einen frei wählbaren Wert verschiebt. Geben Sie bitte den fehlenden Code für die innere Klasse `ListenIterator` an.
Teste Sie Ihre Implementierung wieder mit `StringTransmogrifierTest`.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: StringTransmogrifier erweitern # Lösung: Iterator programmieren
Musterlösung: Musterlösung:
[pr2.lambda.mogrifier_2](../../solutions/src/main/java/pr2/lambda/mogrifier_2/) [pr2.collections.list_iterator](../../solutions/src/main/java/pr2/collections/list_iterator/)

File diff suppressed because one or more lines are too long

View File

@ -1,20 +1,26 @@
# Static Member Class # `List<T>` und dessen Implementierungen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Eine Klasse als statische Elementklasse realisieren. Das Interface `List<T>` und eine passende Implementierung einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.lambda.static_member](../sources/src/main/java/pr2/lambda/static_member/). Gehen Sie in das Paket [pr2.collections.list](../sources/src/main/java/pr2/collections/list/).
In dieser Aufgabe finden Sie bereits ein voll funktionsfähiges Beispiel vor. Lassen Sie es laufen und machen Sie sich mit der Funktionsweise vertraut. (Das Spiel kennen Sie bereits aus einer vorhergehenden Aufgabe, nur die Grafik ist etwas anders.) Im Projekt finden Sie die Klasse `WordCollector` mit deren Hilfe man die Wörter in einem Text analysieren kann. Nach Übergabe eines Dateinamens wird die Datei eingelesen und die vorhandenen Wörter werden gesammelt. Am Ende wird die Liste der Wörter alphabetisch sortiert ausgegeben.
Ihre Aufgabe besteht nun darin, die Klasse `Alien` zu einer statischen Elementklasse der Klasse `GameBoard` zu machen. Leider wurde `WordCollector` von einem Entwickler geschrieben, der nichts von dem Collection-Framework wusste und daher alles mit Array realisiert hat. Hierdurch sind einige sehr komplexe Konstruktionen entstanden.
Lassen Sie das Programm nach der Änderung wieder laufen und schauen überprüfen Sie, dass es sich noch korrekt verhält. Lassen Sie das Programm laufen und betrachten Sie die Ausgabe. Schauen Sie sich die Klasse `WordCollector` an und versuchen Sie die Funktionsweise und die Implementierung genau zu verstehen. Dieser Schritt ist wichtig, um die im Folgenden beschriebenen Änderungen an der Klasse vornehmen zu können, lassen Sie sich also Zeit für diesen Schritt.
Ändern Sie die Klasse nun so, dass anstatt Arrays `List<T>` und deren Implementierungen verwendet werden. Ändern Sie die Schnittstellen und Parameter der Methoden von `String[]` auf `List<String>`. Modifizieren Sie auch die Implementierung der Methoden und versuchen Sie Arrays wo immer möglich durch Listen zu ersetzen. Schauen Sie sich auch die JavaDoc der Klassen `java.util.Arrays` und `java.util.Collections` an, um möglicherweise sehr hilfreiche Methoden zu finden.
__Hinweis:__ Die Konstruktion `String[] words = line.toLowerCase().split("[,. ]");` können Sie nicht durch Listen ersetzen, da die `split`-Methode Arrays verwendet.
Die Datei mit dem Text finden Sie unter [kafka.txt](../sources/src/main/resources/pr2/collections/list/kafka.txt).
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Static Member Class # Lösung: `List<T>` und dessen Implementierungen
Musterlösung: Musterlösung:
[pr2.lambda.static_member](../../solutions/src/main/java/pr2/lambda/static_member/) [pr2.collections.list](../../solutions/src/main/java/pr2/collections/list/)

File diff suppressed because one or more lines are too long

View File

@ -1,20 +1,40 @@
# Iterator schreiben # `Map<T>` verwenden
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Für eine gegebene Klasse einen Iterator schreiben. Das Interface `Map<T>` und seine Implementierungen verwenden, um Daten effizient zu verarbeiten.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.collections.iterator](../sources/src/main/java/pr2/collections/iterator/). Gehen Sie in das Paket [pr2.collections.map](../sources/src/main/java/pr2/collections/map/).
In dieser Aufgabe sollen Sie für eine bereits vorhandene Klasse einen Iterator schreiben. Bei dieser Klasse (`SimpleStack`) handelt es sich um einen sehr einfach (und nicht sehr sicher) programmierten Stack. In dieser Aufgabe geht es darum, die Häufigkeit von Wörtern in einem Text zu analysieren. Ein grundlegendes Gerüst für das Programm ist auch bereits vorgegeben, damit Sie sich auf das Wesentliche konzentrieren können.
Implementieren Sie in `SimpleStack<T>` das Interface `Iterable<T>` und schreiben Sie, wie vom Interface verlangt einen Iterator für die Klasse. Sie sollten hier innere Klasse verwenden, um den Zugriff auf die privaten Attribute von `SimpleStack` zu vereinfachen. Betrachten Sie die Klasse `WordCount`. In dieser fehlen noch einige Elemente, damit das Programm korrekt funktionieren kann.
Benutzen Sie die Tests in `SimpleStackTest`, um zu überprüfen, dass Ihre Implementierung des Iterators richtig funktioniert. Hierzu müssen Sie die entsprechenden Tests allerdings erst einkommentieren. Die innere Klasse `WordFrequency` muss das Sortieren unterstützen. Implementieren Sie daher das Interface `Comparable`.
Fügen Sie in der Klasse `WordCount` an den durch TODO-Kommentare markierten Stellen Code hinzu, der mithilfe einer Map die Worthäufigkeiten bestimmt.
Die Datei mit dem Text finden Sie unter [kafka.txt](../sources/src/main/resources/pr2/collections/map/kafka.txt).
Lassen Sie das Programm laufen. Es sollte eine Ausgabe wie folgt erzeugen:
```console
er: 80
sie: 66
und: 64
die: 59
der: 51
zu: 46
es: 45
nicht: 41
das: 38
in: 35
...
```
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Iterator schreiben # Lösung: `Map<T>` verwenden
Musterlösung: Musterlösung:
[pr2.collections.iterator](../../solutions/src/main/java/pr2/collections/iterator/) [pr2.collections.map](../../solutions/src/main/java/pr2/collections/map/)

View File

@ -1,22 +1,18 @@
# Mithilfe eines Iterators über Daten iterieren # ReverserGeneric
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Den Iterator einer vorhandenen Klasse verwenden, um Daten auszulesen. `Comparable` verstehen und nutzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.collections.iterieren](../sources/src/main/java/pr2/collections/iterieren/). Gehen Sie in das Paket [pr2.collections.reverser_generic](../sources/src/main/java/pr2/collections/reverser_generic/).
Bei dieser Aufgabe werden Sie mit einem `Iterator` über eine Menge von Objekten iterieren. Die Besonderheit besteht darin, dass der Iterator keine feste Menge von Objekten liefert, sondern diese zufällig generiert. Dies ist zwar ungewöhnlich, soll aber zeigen, dass beim Iterieren nicht zwangsläufig bei jedem Durchlauf dieselben Daten kommen. Schreiben Sie bitte eine generische Klasse `Reverser` mit einer Methode `reverse`, der man eine Liste (`java.util.List`) von Objekten übergeben kann und diese absteigend sortiert wird. Stellen Sie durch korrekte Wahl des Typ-Parameters sicher, dass die in der Liste gespeicherten Objekte das Interface `Comparable` implementieren.
Betrachten Sie die Klasse `CoinGenerator` und versuchen Sie deren Funktionsweise zu verstehen. Schauen Sie sich insbesondere an, wie der Iterator in dieser Klasse implementiert ist. Testen Sie Ihre Implementierung mit der Klasse `ReverserTest`.
Modifizieren Sie nun die Klasse `GameBoard` so, dass sie den `CoinGenerator` verwendet, um Münzen zu erzeugen und diese dann auf dem Bildschirm anzuzeigen. Überlegen Sie sich, ob Sie die erzeugten Münzen zwischenspeichern müssen oder ob Sie den Iterator direkt in der `drawGame`-Methode verwenden können.
Implementieren Sie Ihre Lösung und lassen Sie diese laufen, um sie zu testen.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Mithilfe eines Iterators über Daten iterieren # Lösung: ReverserGeneric
Musterlösung: Musterlösung:
[pr2.collections.iterieren](../../solutions/src/main/java/pr2/collections/iterieren/) [pr2.collections.reverser_generic](../../solutions/src/main/java/pr2/collections/reverser_generic/)

View File

@ -1,16 +1,18 @@
# Iterator programmieren # Strings umgekehrt sortieren: Reverser
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Iteratoren verstehen und programmieren. `Comparable` verstehen und nutzen.
## Aufgabe ## Aufgabe
Im Paket [pr2.collections.list_iterator](../sources/src/main/java/pr2/collections/list_iterator/) finden Sie den Code für eine einfach verkettete Liste `Liste<T>`. Gehen Sie in das Paket [pr2.collections.reverser](../sources/src/main/java/pr2/collections/reverser/).
Geben Sie bitte den fehlenden Code für die innere Klasse `ListenIterator` an. Schreiben Sie bitte eine Klasse `Reverser` mit einer Methode `reverse`, der man eine Liste (`java.util.List`) von `String` übergeben kann und die diese dann absteigend sortiert, d.h. als Erstes kommen die Einträge mit Z, dann die mit Y etc.
Testen Sie Ihre Implementierung mit der Klasse `ReverserTest`.
## Abgabe (optional) ## Abgabe (optional)

View File

@ -1,5 +1,5 @@
# Lösung: Iterator programmieren # Lösung: Strings umgekehrt sortieren: Reverser
Musterlösung: Musterlösung:
[pr2.collections.list_iterator](../../solutions/src/main/java/pr2/collections/list_iterator/) [pr2.collections.reverser](../../solutions/src/main/java/pr2/collections/reverser/)

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,14 @@
# `List<T>` und dessen Implementierungen # `Set<T>` und dessen Implementierungen
[Musterlösung](solution/) [Musterlösung](solution/)
## Lernziel ## Lernziel
Das Interface `List<T>` und eine passende Implementierung einsetzen. Das Interface `Set<T>` und eine passende Implementierung einsetzen.
## Aufgabe ## Aufgabe
Gehen Sie in das Paket [pr2.collections.list](../sources/src/main/java/pr2/collections/list/). Gehen Sie in das Paket [pr2.collections.set](../sources/src/main/java/pr2/collections/set/).
Im Projekt finden Sie die Klasse `WordCollector` mit deren Hilfe man die Wörter in einem Text analysieren kann. Nach Übergabe eines Dateinamens wird die Datei eingelesen und die vorhandenen Wörter werden gesammelt. Am Ende wird die Liste der Wörter alphabetisch sortiert ausgegeben. Im Projekt finden Sie die Klasse `WordCollector` mit deren Hilfe man die Wörter in einem Text analysieren kann. Nach Übergabe eines Dateinamens wird die Datei eingelesen und die vorhandenen Wörter werden gesammelt. Am Ende wird die Liste der Wörter alphabetisch sortiert ausgegeben.
@ -16,10 +16,12 @@ Leider wurde `WordCollector` von einem Entwickler geschrieben, der nichts von de
Lassen Sie das Programm laufen und betrachten Sie die Ausgabe. Schauen Sie sich die Klasse `WordCollector` an und versuchen Sie die Funktionsweise und die Implementierung genau zu verstehen. Dieser Schritt ist wichtig, um die im Folgenden beschriebenen Änderungen an der Klasse vornehmen zu können, lassen Sie sich also Zeit für diesen Schritt. Lassen Sie das Programm laufen und betrachten Sie die Ausgabe. Schauen Sie sich die Klasse `WordCollector` an und versuchen Sie die Funktionsweise und die Implementierung genau zu verstehen. Dieser Schritt ist wichtig, um die im Folgenden beschriebenen Änderungen an der Klasse vornehmen zu können, lassen Sie sich also Zeit für diesen Schritt.
Ändern Sie die Klasse nun so, dass anstatt Arrays `List<T>` und deren Implementierungen verwendet werden. Ändern Sie die Schnittstellen und Parameter der Methoden von `String[]` auf `List<String>`. Modifizieren Sie auch die Implementierung der Methoden und versuchen Sie Arrays wo immer möglich durch Listen zu ersetzen. Schauen Sie sich auch die JavaDoc der Klassen `java.util.Arrays` und `java.util.Collections` an, um möglicherweise sehr hilfreiche Methoden zu finden. Ändern Sie die Klasse nun so, dass anstatt Arrays `Set<T>` und deren Implementierungen verwendet werden. Ändern Sie die Schnittstellen und Parameter der Methoden von `String[]` auf `Set<String>` bzw. `List<String>`. Modifizieren Sie auch die Implementierung der Methoden und versuchen Sie Arrays wo immer möglich durch Sets und Listen zu ersetzen. Schauen Sie sich auch die JavaDoc der Klassen `java.util.Arrays` und `java.util.Collections` an, um möglicherweise sehr hilfreiche Methoden zu finden.
__Hinweis:__ Die Konstruktion `String[] words = line.toLowerCase().split("[,. ]");` können Sie nicht durch Listen ersetzen, da die `split`-Methode Arrays verwendet. __Hinweis:__ Die Konstruktion `String[] words = line.toLowerCase().split("[,. ]");` können Sie nicht durch Listen ersetzen, da die `split`-Methode Arrays verwendet.
Die Datei mit dem Text finden Sie unter [kafka.txt](../sources/src/main/resources/pr2/collections/set/kafka.txt).
## Abgabe (optional) ## Abgabe (optional)

Some files were not shown because too many files have changed in this diff Show More