scalatutorial.de

Schnipsel: kurze Scala-Rezepte

Aktualisiert am 24. September 20262 Min. Lesezeit

Manche Aufgaben kommen immer wieder: eine Datei einlesen, Zeit messen, ein Datum formatieren. Hier stehen kurze, erprobte Lösungen in Scala 3 zum Nachschlagen – jeweils mit Hinweis auf die Lektion, die den Hintergrund erklärt.

Textdatei lesen

 Scala 3
import scala.io.Source
import scala.util.Using

val zeilen: List[String] =
  Using.resource(Source.fromFile("daten.txt", "UTF-8"))(_.getLines().toList)

Using.resource schließt die Datei auch im Fehlerfall; die Variante Using(…) liefert ein Try (siehe Exception Handling).

Textdatei schreiben

 Scala 3
import java.nio.file.{Files, Path}
import java.nio.charset.StandardCharsets.UTF_8

Files.writeString(Path.of("ausgabe.txt"), "Stufe für Stufe\n", UTF_8)

Die Java-Standardbibliothek genügt hier völlig. Wer viel mit Dateien arbeitet, greift zur Bibliothek os-lib: os.write(os.pwd / "ausgabe.txt", "Text").

Einfache CSV auswerten

 Scala 3
case class Zeile(ort: String, temperatur: Double)

val daten = zeilen.drop(1)                      // Kopfzeile überspringen
  .map(_.split(";").map(_.trim))
  .collect { case Array(ort, t) => Zeile(ort, t.replace(",", ".").toDouble) }

daten.groupMapReduce(_.ort)(_.temperatur)(math.max)

Für echte CSV-Dateien mit Anführungszeichen und Zeilenumbrüchen in Feldern lohnt eine Bibliothek. Mehr zu groupMapReduce unter Map.

Zeit messen

 Scala 3
def gemessen[A](name: String)(block: => A): A =
  val start = System.nanoTime
  val ergebnis = block
  println(f"$name: ${(System.nanoTime - start) / 1e6}%.1f ms")
  ergebnis

val summe = gemessen("Summe") { (1 to 10_000_000).map(_.toLong).sum }

Der By-Name-Parameter block: => A sorgt dafür, dass der Block erst innerhalb der Messung ausgeführt wird (siehe Funktionen).

Zufallszahlen

 Scala 3
import scala.util.Random

Random.nextInt(6) + 1                   // Würfel: 1 bis 6
Random.between(10, 20)                  // 10 bis 19
Random.shuffle(List("a", "b", "c"))     // zufällige Reihenfolge
val r = new Random(42)                  // mit festem Startwert, reproduzierbar

Datum und Uhrzeit

 Scala 3
import java.time.{LocalDate, LocalDateTime}
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit

val heute = LocalDate.now
val format = DateTimeFormatter.ofPattern("dd.MM.yyyy")
heute.format(format)                              // z. B. "24.09.2026"
LocalDate.parse("01.05.2027", format)             // Text → Datum
ChronoUnit.DAYS.between(heute, LocalDate.of(2026, 12, 24))   // Tage bis Heiligabend

Umgebungsvariablen und Argumente

 Scala 3
val port = sys.env.get("PORT").flatMap(_.toIntOption).getOrElse(8080)
val debug = sys.props.get("debug").contains("true")

Kommandozeilenargumente nimmt am einfachsten die @main-Methode entgegen, siehe Hello world.

Wiederholen, bis es klappt

 Scala 3
import scala.util.{Try, Success, Failure}

def nochmal[A](versuche: Int)(aktion: => A): Try[A] =
  Try(aktion) match
    case Failure(_) if versuche > 1 => nochmal(versuche - 1)(aktion)
    case ergebnis                    => ergebnis

nochmal(3) { ladeVomServer() }

Liste in Blöcke teilen

 Scala 3
(1 to 10).grouped(4).toList
// List(Vector(1, 2, 3, 4), Vector(5, 6, 7, 8), Vector(9, 10))

List("a", "b", "c", "d").sliding(2).toList
// List(List(a, b), List(b, c), List(c, d))

Häufigstes Element

 Scala 3
val woerter = List("scala", "java", "scala", "kotlin", "scala")
woerter.groupMapReduce(identity)(_ => 1)(_ + _).maxBy(_._2)
// (scala, 3)

Text in Wörter zerlegen

 Scala 3
"Stufe um Stufe, Schritt für Schritt!".toLowerCase
  .split("[^\\p{L}]+").filter(_.nonEmpty).toList
// List(stufe, um, stufe, schritt, für, schritt)

\p{L} steht für jeden Buchstaben, auch Umlaute. Mehr zu Zeichenketten unter Strings.

Enum aus Text

 Scala 3
enum Stufe:
  case Einstieg, Sprachkern, Objekte

def stufe(s: String): Option[Stufe] =
  Stufe.values.find(_.toString.equalsIgnoreCase(s))

stufe("einstieg")   // Some(Einstieg)

Stufe.valueOf(s) gibt es auch, wirft aber bei unbekanntem Text eine Ausnahme – die Variante mit Option ist robuster (siehe Option).