C2F: Higher-Order Functions erstellen

Ich kann Funktionen als Argumente für andere Funktionen verwenden und dadurch höherwertige Funktionen erstellen.

Lernziele

# Lernziel Beantwortet in
1 Ich kann eine Funktion schreiben, die eine andere Funktion als Parameter entgegennimmt und aufruft. 1. Funktion als Argument übergeben
2 Ich kann eine eigene Higher-Order Function implementieren (z.B. eine eigene apply-Funktion). 2. Eigene Higher-Order Function schreiben
3 Ich kann das Callback-Muster mit Higher-Order Functions umsetzen, um flexiblen, wiederverwendbaren Code zu schreiben. 3. Callback-Muster anwenden

1. Funktion als Argument übergeben

Eine Higher-Order Function ist eine Funktion, die mindestens eine Funktion als Argument entgegennimmt oder eine Funktion als Rückgabewert liefert.

static int applyTwice(Function<Integer, Integer> func, int value) {
    return func.apply(func.apply(value));
}

System.out.println(applyTwice(x -> x + 3, 7));   // 13  (7→10→13)
System.out.println(applyTwice(x -> x * 2, 5));    // 20  (5→10→20)

applyTwice ist eine Higher-Order Function, weil sie eine Function<Integer, Integer> als Parameter entgegennimmt. Die konkrete Logik wird erst beim Aufruf festgelegt.

Bekannte Higher-Order Functions in Java

Die Stream API besteht fast nur aus Higher-Order Functions:

Methode Funktionsargument Zweck
map() Function<T, R> Jedes Element transformieren
filter() Predicate<T> Elemente nach Kriterium auswählen
sorted() Comparator<T> Sortierreihenfolge festlegen
forEach() Consumer<T> Aktion pro Element ausführen
reduce() BinaryOperator<T> Alle Elemente zusammenfassen

2. Eigene Higher-Order Function schreiben

Eigenes applyToAll (wie map, aber ohne Streams)

static List<Integer> applyToAll(List<Integer> list, Function<Integer, Integer> func) {
    var result = new ArrayList<Integer>();
    for (var item : list) {
        result.add(func.apply(item));
    }
    return result;
}

var numbers = List.of(1, 2, 3, 4);
var doubled = applyToAll(numbers, x -> x * 2);      // [2, 4, 6, 8]
var squared = applyToAll(numbers, x -> x * x);       // [1, 4, 9, 16]
var negated = applyToAll(numbers, x -> -x);           // [-1, -2, -3, -4]

Die gleiche Funktion applyToAll kann drei völlig verschiedene Operationen ausführen, weil die Logik von aussen übergeben wird.

Funktion zurückgeben: createMultiplier

static Function<Integer, Integer> createMultiplier(int factor) {
    return x -> x * factor;
}

var doubler = createMultiplier(2);
var tripler = createMultiplier(3);

System.out.println(doubler.apply(5));  // 10
System.out.println(tripler.apply(5));  // 15

createMultiplier ist eine Higher-Order Function, weil sie eine Funktion zurückgibt. Das Lambda x -> x * factor bildet einen Closure über den Parameter factor.


3. Callback-Muster anwenden

Beim Callback-Muster übergibt man eine Funktion, die zu einem bestimmten Zeitpunkt aufgerufen wird. Das ermöglicht flexiblen, wiederverwendbaren Code.

Beispiel: Listenverarbeitung mit Logging

static <T> List<T> processWithCallback(
        List<T> items,
        Predicate<T> filter,
        Consumer<T> onMatch) {
    var result = new ArrayList<T>();
    for (var item : items) {
        if (filter.test(item)) {
            onMatch.accept(item);
            result.add(item);
        }
    }
    return result;
}

var numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);

// Callback: Treffer auf der Konsole ausgeben
var even = processWithCallback(
    numbers,
    x -> x % 2 == 0,
    x -> System.out.println("Gefunden: " + x)
);
// Gefunden: 2
// Gefunden: 4
// Gefunden: 6
// Gefunden: 8

Beispiel: Flexible Validierung

static boolean validateAll(List<String> inputs, Predicate<String> rule) {
    return inputs.stream().allMatch(rule);
}

var emails = List.of("a@b.ch", "c@d.com", "e@f.org");

var allContainAt = validateAll(emails, s -> s.contains("@"));     // true
var allDotCh     = validateAll(emails, s -> s.endsWith(".ch"));   // false

Die Validierungslogik wird per Callback übergeben. validateAll selbst muss nicht wissen, welche Regel geprüft wird.


This site uses Just the Docs, a documentation theme for Jekyll.