Update of exercises

main
Thomas Smits 2024-11-27 14:28:12 +01:00
parent 52cb569f25
commit 86415254cb
42 changed files with 763 additions and 18 deletions

View File

@ -1,6 +1,6 @@
# Einen generischen Typ schreiben
## Lernziel
[Musterlösung](solution/)
Einen vorhandenen Typ so umgestalten, dass er als generischer Typ verwendet werden kann.

View File

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

View File

@ -1,6 +1,6 @@
# Generische Klasse Pair schreiben
## Lernziel
[Musterlösung](solution/)
Von einem generischen Typ erben.

View File

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

View File

@ -1,6 +1,6 @@
# Generische Klasse Pair erweitern: NumberPair
## Lernziel
[Musterlösung](solution/)
Von einem generischen Typ erben.

View File

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

View File

@ -1,6 +1,6 @@
# Generische Klasse Pair erweitern: SamePair
## Lernziel
[Musterlösung](solution/)
Von einem generischen Typ erben.

View File

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

View File

@ -1,6 +1,6 @@
# PairList
## Lernziel
[Musterlösung](solution/)
Sammlungen von Objekten eines generischen Typs erstellen.

View File

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

View File

@ -1,6 +1,6 @@
# Wildcard benutzen
## Lernziel
[Musterlösung](solution/)
Wildcards einsetzen.

View File

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

View File

@ -1,6 +1,6 @@
# Generische Queue
## Lernziel
[Musterlösung](solution/)
Einen komplexeren generischen Typ entwickeln.

View File

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

View File

@ -1,6 +1,6 @@
# `super` und `extends` einsetzen
## Lernziel
[Musterlösung](solution/)
Methoden unter Verwendung von `super` und `extends` gestalten, sodass sie flexibel auch mit Sub- bzw. Supertypen umgehen können.

View File

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

View File

@ -1,6 +1,6 @@
# Generische Typen zusammen mit Wildcards einsetzen
## Lernziel
[Musterlösung](solution/)
Gebundene und ungebundene Wildcards einsetzen.

View File

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

View File

@ -73,15 +73,15 @@ Hinweise zur nötigen Softwareausstattung finden Sie [hier](help/softwareausstat
| 59. | Input und Output | [Rot13-Verschlüsselung](Input_und_Output_014/readme.md) | [](Input_und_Output_014/solution/) |
| 60. | Input und Output | [Datei zerhacken](Input_und_Output_015/readme.md) | [](Input_und_Output_015/solution/) |
| 61. | Input und Output | [Serialisierung](Input_und_Output_016/readme.md) | [](Input_und_Output_016/solution/) |
| 62. | Generische Typen | [Einen generischen Typ schreiben](Generische_Typen_001/readme.md) | |
| 63. | Generische Typen | [Generische Klasse Pair schreiben](Generische_Typen_002/readme.md) | |
| 64. | Generische Typen | [Generische Klasse Pair erweitern: NumberPair](Generische_Typen_003/readme.md) | |
| 65. | Generische Typen | [Generische Klasse Pair erweitern: SamePair](Generische_Typen_004/readme.md) | |
| 66. | Generische Typen | [PairList](Generische_Typen_005/readme.md) | |
| 67. | Generische Typen | [Wildcard benutzen](Generische_Typen_006/readme.md) | |
| 68. | Generische Typen | [Generische Queue](Generische_Typen_007/readme.md) | |
| 69. | Generische Typen | [`super` und `extends` einsetzen](Generische_Typen_008/readme.md) | |
| 70. | Generische Typen | [Generische Typen zusammen mit Wildcards einsetzen](Generische_Typen_009/readme.md) | |
| 62. | Generische Typen | [Einen generischen Typ schreiben](Generische_Typen_001/readme.md) | [](Generische_Typen_001/solution/) |
| 63. | Generische Typen | [Generische Klasse Pair schreiben](Generische_Typen_002/readme.md) | [](Generische_Typen_002/solution/) |
| 64. | Generische Typen | [Generische Klasse Pair erweitern: NumberPair](Generische_Typen_003/readme.md) | [](Generische_Typen_003/solution/) |
| 65. | Generische Typen | [Generische Klasse Pair erweitern: SamePair](Generische_Typen_004/readme.md) | [](Generische_Typen_004/solution/) |
| 66. | Generische Typen | [PairList](Generische_Typen_005/readme.md) | [](Generische_Typen_005/solution/) |
| 67. | Generische Typen | [Wildcard benutzen](Generische_Typen_006/readme.md) | [](Generische_Typen_006/solution/) |
| 68. | Generische Typen | [Generische Queue](Generische_Typen_007/readme.md) | [](Generische_Typen_007/solution/) |
| 69. | Generische Typen | [`super` und `extends` einsetzen](Generische_Typen_008/readme.md) | [](Generische_Typen_008/solution/) |
| 70. | Generische Typen | [Generische Typen zusammen mit Wildcards einsetzen](Generische_Typen_009/readme.md) | [](Generische_Typen_009/solution/) |
| 71. | Geschachtelte Klassen | [Eigene compare-Methode schreiben](Geschachtelte_Klassen_001/readme.md) | |
| 72. | Geschachtelte Klassen | [Innere Klasse Beobachter](Geschachtelte_Klassen_002/readme.md) | |
| 73. | Geschachtelte Klassen | [Callback mit anonymer Klasse realisieren](Geschachtelte_Klassen_003/readme.md) | |

View File

@ -0,0 +1,90 @@
package pr2.generics.einfach;
/**
* Eine einfache, verkettete Liste.
*
* @param <T> Typ der gespeicherten Objekte
*/
public class Liste<T> {
/**
* Referenz auf den ersten Knoten.
*/
private ListeNode<T> first;
/**
* Referenz auf den aktuellen Knoten.
*/
private ListeNode<T> current;
/**
* Fügt ein neues Element an das Ende der Liste an.
*
* @param data das Element
*/
public void add(T data) {
ListeNode<T> nextNode = new ListeNode<>(data);
if (current == null) {
// Liste komplett leer
first = nextNode;
current = nextNode;
}
else {
current.next = nextNode;
current = nextNode;
}
}
/**
* Liest das Element an der gegebenen Position.
*
* @param index Index, beginnend bei 0.
* @return Das Element oder {@code null}, wenn es nicht gefunden wurde.
*/
public T get(int index) {
int count = 0;
ListeNode<T> node = first;
while ((node != null) && (count < index)) {
node = node.next;
count++;
}
if ((count == index) && (node != null)) {
return node.data;
}
else {
// index does not exist
return null;
}
}
/**
* Löscht die Liste und entfernt alle Elemente.
*/
public void clear() {
first = null;
current = null;
}
/**
* Liefert die Anzahl der Elemente der Liste zurück.
*
* @return die Anzahl der Elemente.
*/
public int size() {
int count = 0;
ListeNode<T> node = first;
while (node != null) {
node = node.next;
count++;
}
return count;
}
}

View File

@ -0,0 +1,30 @@
package pr2.generics.einfach;
/**
* Interne Repräsentation der Knoten in der Liste.
*
* @param <T> Typ der gespeicherten Daten.
*/
class ListeNode<T> {
/**
* Daten.
*/
T data;
/**
* Referenz auf den nächsten Knoten.
*/
ListeNode<T> next;
/**
* Legt einen neuen Knoten an.
*
* @param data daten, die gespeichert werden
*/
ListeNode(T data) {
this.data = data;
}
}

View File

@ -0,0 +1,61 @@
package pr2.generics.einfach.test;
import org.junit.jupiter.api.Test;
import pr2.generics.einfach.Liste;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* Test für die Liste.
*/
public class ListeTest {
/**
* Testet das Hinzufügen und Löschen der Liste.
*/
@Test
void testAddAndClear() {
Liste<String> l = new Liste<>();
assertEquals(0, l.size());
l.add("Hallo");
assertEquals(1, l.size());
l.add("Hugo");
assertEquals(2, l.size());
l.add("Peter");
l.add("Alfons");
assertEquals(4, l.size());
l.clear();
assertEquals(0, l.size());
}
/**
* Testet das Lesen von Elementen.
*/
@Test
void testGet() {
Liste<String> l = new Liste<>();
l.add("Hallo");
l.add("Hugo");
l.add("Peter");
l.add("Alfons");
assertNull(l.get(-1));
assertNull(l.get(4));
assertEquals("Hallo", l.get(0));
assertEquals("Hugo", l.get(1));
assertEquals("Peter", l.get(2));
assertEquals("Alfons", l.get(3));
assertEquals(4, l.size());
l.clear();
assertEquals(0, l.size());
assertNull(l.get(0));
assertNull(l.get(1));
assertNull(l.get(2));
assertNull(l.get(3));
}
}

View File

@ -0,0 +1,15 @@
package pr2.generics.number_pair;
public class Main {
public static void main(String[] args) {
var note = new Pair<String, Integer>("Peter", 1);
var name = new Pair<String, String>("Peter", "Meier");
var tel = new NumberPair<Integer>(621, 292122);
System.out.printf("%s:%d\n", note.getFirst(), note.getSecond());
System.out.printf("%s %s\n", name.getFirst(), name.getSecond());
System.out.printf("%d %d\n", tel.getFirst(), tel.getSecond());
}
}

View File

@ -0,0 +1,8 @@
package pr2.generics.number_pair;
public class NumberPair<T extends Number> extends Pair<T, T> {
public NumberPair(T first, T second) {
super(first, second);
}
}

View File

@ -0,0 +1,20 @@
package pr2.generics.number_pair;
public class Pair<T, V> {
private final T first;
private final V second;
public Pair(T first, V second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public V getSecond() {
return second;
}
}

View File

@ -0,0 +1,17 @@
package pr2.generics.pair;
public class Main {
public static void main(String[] args) {
var note1 = new Pair<String, Integer>("Peter", 1);
var note2 = new Pair<String, Integer>("Frank", 3);
var note3 = new Pair<String, Integer>("Sabine", 1);
var name = new Pair<String, String>("Peter", "Meier");
System.out.printf("%s:%d\n", note1.getFirst(), note1.getSecond());
System.out.printf("%s:%d\n", note2.getFirst(), note1.getSecond());
System.out.printf("%s:%d\n", note3.getFirst(), note1.getSecond());
System.out.printf("%s %s\n", name.getFirst(), name.getSecond());
}
}

View File

@ -0,0 +1,20 @@
package pr2.generics.pair;
public class Pair<T, V> {
private final T first;
private final V second;
public Pair(T first, V second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public V getSecond() {
return second;
}
}

View File

@ -0,0 +1,19 @@
package pr2.generics.pairlist;
public class Main {
public static void main(String[] args) {
var note1 = new Pair<String, Integer>("Peter", 1);
var note2 = new Pair<String, Integer>("Frank", 3);
var note3 = new Pair<String, Integer>("Sabine", 1);
var pl = new PairList<String, Integer>(3);
pl.add(note1);
pl.add(note2);
pl.add(note3);
for (int i = 0; i < 3; i++) {
System.out.printf("%s:%d\n", pl.get(i).getFirst(),
pl.get(i).getSecond());
}
}
}

View File

@ -0,0 +1,20 @@
package pr2.generics.pairlist;
public class Pair<T, V> {
private final T first;
private final V second;
public Pair(T first, V second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public V getSecond() {
return second;
}
}

View File

@ -0,0 +1,20 @@
package pr2.generics.pairlist;
public class PairList<T, V> {
protected final Pair<T, V>[] elements;
protected int pos;
@SuppressWarnings("unchecked")
public PairList(int size) {
elements = (Pair<T, V>[]) new Pair[size];
}
public void add(Pair<T, V> element) {
elements[pos++] = element;
}
public Pair<T, V> get(int index) {
return elements[index];
}
}

View File

@ -0,0 +1,11 @@
package pr2.generics.printer;
import java.util.Collection;
public class CollectionPrinter {
public static void print(Collection<?> collection) {
for (Object object : collection) {
System.out.println(object);
}
}
}

View File

@ -0,0 +1,23 @@
package pr2.generics.printer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> ls = new ArrayList<>();
List<Integer> li = new ArrayList<>();
ls.add("PR2");
ls.add("ist");
ls.add("cool");
Set<String> s = new HashSet<>(ls);
li.add(23);
li.add(42);
CollectionPrinter.print(ls);
CollectionPrinter.print(li);
CollectionPrinter.print(s);
}
}

View File

@ -0,0 +1,39 @@
package pr2.generics.queue;
public class Queue<T> {
private final T[] elements;
private int pos = 0;
private int pos2 = 0;
@SuppressWarnings("unchecked")
public Queue(int size) {
elements = (T[]) new Object[size];
}
public void offer(T element) {
elements[pos] = element;
pos++;
pos = pos % elements.length;
}
public T poll() {
T element = elements[pos2];
elements[pos2] = null;
pos2++;
pos2 = pos2 % elements.length;
return element;
}
public void addAll(Queue<? extends T> other) {
for (T t : other.elements) {
offer(t);
}
}
public void copyInto(Queue<? super T> other) {
for (T t : elements) {
other.offer(t);
}
}
}

View File

@ -0,0 +1,15 @@
package pr2.generics.same_pair;
public class Main {
public static void main(String[] args) {
var note = new Pair<String, Integer>("Peter", 1);
var name = new SamePair<String>("Peter", "Meier");
var tel = new SamePair<Integer>(621, 2009992);
System.out.printf("%s:%d\n", note.getFirst(), note.getSecond());
System.out.printf("%s %s\n", name.getFirst(), name.getSecond());
System.out.printf("%d %d\n", tel.getFirst(), tel.getSecond());
}
}

View File

@ -0,0 +1,20 @@
package pr2.generics.same_pair;
public class Pair<T, V> {
private final T first;
private final V second;
public Pair(T first, V second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public V getSecond() {
return second;
}
}

View File

@ -0,0 +1,8 @@
package pr2.generics.same_pair;
public class SamePair<T> extends Pair<T, T> {
public SamePair(T first, T second) {
super(first, second);
}
}

View File

@ -0,0 +1,108 @@
package pr2.generics.super_extends;
/**
* Eine einfache, verkettete Liste.
*
* @param <T> Typ der gespeicherten Objekte
*/
public class Liste<T> {
/**
* Referenz auf den ersten Knoten.
*/
private ListeNode<T> first;
/**
* Referenz auf den aktuellen Knoten.
*/
private ListeNode<T> current;
/**
* Fügt ein neues Element an das Ende der Liste an.
*
* @param data das Element
*/
public void add(T data) {
ListeNode<T> nextNode = new ListeNode<>(data);
if (current == null) {
// Liste komplett leer
first = nextNode;
current = nextNode;
}
else {
current.next = nextNode;
current = nextNode;
}
}
/**
* Liest das Element an der gegebenen Position.
*
* @param index Index, beginnend bei 0.
* @return Das Element oder {@code null}, wenn es nicht gefunden wurde.
*/
public T get(int index) {
int count = 0;
ListeNode<T> node = first;
while ((node != null) && (count < index)) {
node = node.next;
count++;
}
if ((count == index) && (node != null)) {
return node.data;
}
else {
// index does not exist
return null;
}
}
/**
* Löscht die Liste und entfernt alle Elemente.
*/
public void clear() {
first = null;
current = null;
}
/**
* Liefert die Anzahl der Elemente der Liste zurück.
*
* @return die Anzahl der Elemente.
*/
public int size() {
int count = 0;
ListeNode<T> node = first;
while (node != null) {
node = node.next;
count++;
}
return count;
}
/**
* Kopiert alle Elemente dieser Liste in die andere Liste.
*
* @param other die andere Liste.
*/
public void copyInto(Liste<? super T> other) {
for (int i = 0; i < size(); i++) {
other.add(get(i));
}
}
/**
* Füllt diese Liste mit dem Inhalt der übergebenen Liste.
*
* @param other die andere Liste.
*/
public void fillFrom(Liste<? extends T> other) {
other.copyInto(this);
}
}

View File

@ -0,0 +1,28 @@
package pr2.generics.super_extends;
/**
* Interne Repräsentation der Knoten in der Liste.
*
* @param <T> Typ der gespeicherten Daten.
*/
class ListeNode<T> {
/**
* Daten.
*/
T data;
/**
* Referenz auf den nächsten Knoten.
*/
ListeNode<T> next;
/**
* Legt einen neuen Knoten an.
*
* @param data daten, die gespeichert werden
*/
ListeNode(T data) {
this.data = data;
}
}

View File

@ -0,0 +1,42 @@
package pr2.generics.super_extends.test;
import org.junit.jupiter.api.Test;
import pr2.generics.super_extends.Liste;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Test für die Liste.
*/
public class ListeTest {
/**
* Testet das Umkopieren.
*/
@Test
void testAddAndClear() {
Liste<String> ls = new Liste<>();
Liste<Object> lo = new Liste<>();
ls.add("Hallo");
ls.add("Hugo");
ls.add("Peter");
ls.add("Alfons");
ls.copyInto(lo);
assertEquals("Hallo", lo.get(0));
assertEquals("Hugo", lo.get(1));
assertEquals("Peter", lo.get(2));
assertEquals("Alfons", lo.get(3));
lo = new Liste<>();
lo.fillFrom(ls);
assertEquals("Hallo", lo.get(0));
assertEquals("Hugo", lo.get(1));
assertEquals("Peter", lo.get(2));
assertEquals("Alfons", lo.get(3));
}
}

View File

@ -0,0 +1,35 @@
package pr2.generics.wildcards;
/**
* Klasse zum Ausdrucken von Listen.
*/
public class ListHelper {
/**
* Druckt alle Elemente der Liste auf der Konsole aus.
*
* @param liste Die zu druckende Liste.
*/
public static void printList(SimpleList<?> liste) {
for (Object o : liste) {
System.out.println(o);
}
}
/**
* Summiert die Elemente der Liste. Deswegen können nur Listen übergeben
* werden, deren Elemente mindestens vom Typ {@code Number} sind.
*
* @param liste Die Liste, deren Elemente summiert werden sollen.
* @return das Ergebnis
*/
public static double sumList(SimpleList<? extends Number> liste) {
double sum = 0;
for (Number number : liste) {
sum += number.doubleValue();
}
return sum;
}
}

View File

@ -0,0 +1,39 @@
package pr2.generics.wildcards;
/**
* Ausgabe der Liste.
*/
public final class Main {
/**
* Constructor.
*/
private Main() {
// keine Instanzen
}
/**
* Haupt-Methode.
*
* @param args Kommandozeilenargumente.
*/
public static void main(String[] args) {
SimpleList<String> l1 = new SimpleList<>();
l1.add("Dies");
l1.add("ist");
l1.add("ein");
l1.add("Test");
l1.add(".");
SimpleList<Integer> l2 = new SimpleList<>();
l2.add(1);
l2.add(2);
l2.add(3);
l2.add(4);
l2.add(5);
ListHelper.printList(l1);
ListHelper.printList(l2);
System.out.println(ListHelper.sumList(l2));
}
}

View File

@ -0,0 +1,12 @@
package pr2.generics.wildcards;
import java.util.ArrayList;
/**
* Listenklasse.
*
* @param <T> Typ, der in der Liste gespeichert wird.
*/
public class SimpleList<T> extends ArrayList<T> {
// nothing here
}