Fold oder Reduce in Kotlin: Die ewige Frage der Anfänger
\n\nWenn Sie auch nur eine Woche in Kotlin programmieren, sind Sie mit ziemlicher Sicherheit bereits auf die Funktionen fold und reduce gestoßen. Auf den ersten Blick tun sie dasselbe: Sie durchlaufen eine Sammlung und akkumulieren ein Ergebnis. Aber der Teufel steckt, wie immer, im Detail. Die falsche Wahl kann zu Bugs, Ausnahmen oder einfach zu unschönem Code führen.
In diesem Artikel analysieren wir den Unterschied zwischen fold und reduce in Kotlin, sehen uns Live-Beispiele aus echten Projekten an und merken uns ein für alle Mal, wann welche Funktion zu verwenden ist. Los geht's!
\n\nWas sind fold und reduce? Grundlegendes Verständnis
\n\nBeide Funktionen gehören zu den terminalen Operationen für Sammlungen. Sie nehmen alle Elemente und falten sie zu einem einzigen Wert zusammen. Stellen Sie sich vor, Sie haben einen Stapel Pfannkuchen und möchten einen großen Burger daraus machen. fold und reduce sind zwei verschiedene Falttechniken.
Reduce: Der minimalistische Ansatz
\n\nDie Funktion reduce verwendet das erste Element der Sammlung als Anfangswert des Akkumulators. Das bedeutet, dass sie einfach nicht mit einer leeren Sammlung arbeiten kann – es wird eine UnsupportedOperationException ausgelöst.
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.reduce { acc, i -> acc + i }\nprintln(sum) // 15\n\nHier ist acc anfangs gleich 1 (das erste Element), dann wird 2 hinzugefügt, dann 3 und so weiter. Ganz einfach und elegant, aber es gibt einen Haken.
Fold: Kontrolle über den Anfang
\n\nfold erfordert im Gegensatz zu reduce, dass Sie explizit einen Anfangswert angeben. Das gibt Ihnen die volle Kontrolle und, was noch wichtiger ist, ermöglicht die Arbeit mit leeren Sammlungen.
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.fold(0) { acc, i -> acc + i }\nprintln(sum) // 15\n\nval emptyList = listOf<Int>()\nval emptySum = emptyList.fold(0) { acc, i -> acc + i }\nprintln(emptySum) // 0, kein Fehler!\n\nSehen Sie den Unterschied? fold gibt den Anfangswert zurück, wenn die Sammlung leer ist. reduce würde in einer solchen Situation abstürzen.
Wesentliche Unterschiede zwischen fold und reduce in Kotlin
\n\nLassen Sie uns das Wissen systematisieren. Hier ist eine Tabelle, die Ihnen hilft, sich schnell zu orientieren:
\n\n- \n
- Anfangswert: Bei
foldgeben Sie ihn selbst vor. Beireduceist es das erste Element der Sammlung. \n - Ergebnistyp: Bei
foldkann sich der Ergebnistyp vom Elementtyp unterscheiden (z.B. Sie addieren Int, erhalten aber einen String). Beireducestimmt der Ergebnistyp immer mit dem Elementtyp überein. \n - Leere Sammlung:
foldverarbeitet sie normal (gibt den Anfangswert zurück).reducewirft eine Ausnahme. \n - Leistung: Beide Funktionen arbeiten mit O(n). Der Leistungsunterschied ist vernachlässigbar. \n
Schauen wir uns das nun im Code an.
\n\nBeispiel 1: Unterschiedliche Typen von Akkumulator und Elementen
\n\nAngenommen, wir haben eine Liste von Zahlen und möchten einen String erhalten – ihre Summe in lesbarer Form. fold meistert das hervorragend, da sich der Typ des Akkumulators (String) vom Typ der Elemente (Int) unterscheidet.
val numbers = listOf(1, 2, 3)\nval result = numbers.fold("Summe: ") { acc, i -> "$acc$i " }\nprintln(result) // "Summe: 1 2 3 "\n\nVersuchen Sie dasselbe mit reduce – der Compiler wird einen Fehler ausgeben, weil reduce erfordert, dass der Typ des Akkumulators mit dem Typ der Elemente übereinstimmt.
Beispiel 2: Summenberechnung unter Berücksichtigung eines Anfangswerts
\n\nEine häufige Aufgabe: Berechnung des Gesamtbetrags von Bestellungen, wobei wir bereits einen Anfangsguthaben auf dem Konto haben.
\n\nval orders = listOf(100, 250, 75)\nval initialBalance = 500\nval totalBalance = orders.fold(initialBa