# Nachdenkzettel: Wahlpflicht Collections

### 1. Verwendung von Collections

Angenommen Sie entwickeln ein kleines Werkzeug, das Messdatenreihen aus einer Datei einlesen soll. Die Datenmenge kann schwanken. Außerdem sollen neue Messdatenreihen von weiteren Sensoren zeitlich sortiert eingefügt werden.

a) Welche Form von Collection würden Sie verwenden und warum?       
b) Ein Kollege schlägt vor, eine `CopyOnWriteArrayList` zu verwenden. Verwenden Sie das folgende Benchmark-Szenario, um zu messen, wie lange das Einfügen in der Mitte der Liste dauert:  

```java
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100_000; i++) {
    list.add(i);
}

long t0 = System.nanoTime();
for (int k = 0; k < 10_000; k++) {
    list.add(list.size() / 2, -1);
}
long t1 = System.nanoTime();

System.out.println("time: " + (t1 - t0));
```
c) Vergleichen Sie Ihr Ergebnis und erklären Sie warum Benchmarks zu Collections manchmal kontraintuitiv sind.  
d) Betrachten Sie folgendes Diagramm (Quelle: [DZone.com - Java Collection Performance](https://dzone.com/articles/java-collection-performance)):
![Java Collection Benchmark](ListPerf.png)  
e) Formulieren Sie zwei einfache Entscheidungsregeln, die Sie sich merken können, wenn Sie Listen auswählen.  Interpretieren Sie dabei das folgende Benchmarkdiagram. Was fällt dabei auf? Wann nutzen Sie welche Collection?  

### 2. Iterator

Sie haben eine einfache Collection-Klasse für Aufgaben vom Typ `Task`.  Die Klasse `TaskList` implementiert `Iterable<Task>`, damit man mit `for-each` über mehrere Tasks laufen kann.

```java
public class Task {
    private final String name;
    private final boolean done;

    public Task(String name, boolean done) { this.name = name; this.done = done; }
    public boolean isDone() { return done; } 
} 

public class TaskList<T extends Task> implements Iterable<T> {
    private final List<T> tasks = new ArrayList<>();
 
    @Override
    public Iterator<T> iterator() { return tasks.iterator(); }

    public List<T> asList() { return tasks; }
    public void add(T t) { tasks.add(t); }
}
```
Jetzt möchten Sie alle erledigten Aufgaben aus der `TaskList` entfernen. 
```java
TaskList<Task> tl = new TaskList<>();
tl.add(new Task("mail", false));
tl.add(new Task("backup", true));
tl.add(new Task("cleanup", true));
tl.add(new Task("report", false));

for (Task t : tl) {
    if (t.isDone()) {
        tl.asList().remove(t);
    }
}
```
a) Welchen Fehler erhalten Sie und warum?  
b) Schreiben Sie die Schleife so um, dass das Entfernen korrekt funktioniert. Verwenden Sie den Iterator selbst.  
c) Schreiben Sie eine Kurzvariante, die ohne explizite Iteration auskommt (Tipp: schauen Sie mal nach der Methode `removeIf()`).  

### 3. Collections in Ihrem Projekt
a) Nennen Sie ein konkretes Beispiel aus Ihrem Projekt, bei dem Sie eine Collection verwenden. Beschreiben Sie kurz, welche Objekte gespeichert werden und wofür.  
b) Begründen Sie die Wahl und Zugriff auf die gewählte Collection. Gehen Sie konkret auf die Aspekte Generics, Zugriffszeiten und Sortierbarkeit ein.  
c) Beschreiben Sie Ihren Vorschlag zur Nutzung von Collections in ihrem Projekt einer KI/LLM Ihrer Wahl und fassen Sie dessen Ausgabe von Vor- und Nachteilen gegenüber anderen Collection-Types (List, Set, Hash, etc.) prägnant zusammen.     