EMZETT.
Login

Kurz: Scala hat eine reiche, standardmäßig unveränderliche Collection-Bibliothek: List, Vector, Set, Map, Seq, Array. Operationen liefern neue Collections.

Teil des Kurses Scala

Kapitel 3 von 8 im Kurs Scala (Abschnitt „Funktional denken“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Collections

Scala hat eine reiche, standardmäßig unveränderliche Collection-Bibliothek: List, Vector, Set, Map, Seq, Array. Operationen liefern neue Collections.

@main def main(): Unit =
  val z = List(5, 3, 9, 1, 7)
  println(s"${z.head} ${z.tail} ${z.last} ${z.length} ${z(2)} ${z.take(2)} ${z.drop(3)}")
  println(s"${0 :: z} ${z :+ 100} ${z ++ List(8)} ${z.reverse} ${z.sorted} ${z.sortBy(-_)} ${z.sortWith(_ > _)}")
  println(s"${z.map(_ * 2)} ${z.filter(_ > 4)} ${z.sum} ${z.product} ${z.min} ${z.max} ${z.size}")
  println(s"${z.exists(_ > 8)} ${z.forall(_ > 0)} ${z.count(_ % 2 == 1)} ${z.find(_ > 5)} ${z.indexOf(9)} ${z.contains(3)}")
  println(s"${z.foldLeft(0)(_ + _)} ${z.reduce(_ max _)} ${z.partition(_ > 4)} ${z.zip("abcde")} ${z.sliding(2).toList}")
  println(s"${z.grouped(2).toList} ${z.takeWhile(_ > 2)} ${z.dropWhile(_ > 2)} ${z.span(_ > 2)} ${z.splitAt(2)}")
  println(s"${List(List(1, 2), List(3)).flatten} ${List("ab", "cd").flatMap(_.toList)} ${z.distinct} ${z.mkString(", ")} ${z.mkString("[", ";", "]")}")
  println(s"${List(1, 2, 2, 3, 3, 3).groupBy(identity).view.mapValues(_.size).toMap.toList.sorted}")
  println(s"${List("a", "bb", "ccc").map(_.length)} ${(1 to 5).toList.scanLeft(0)(_ + _)} ${List.fill(3)("x")} ${List.range(0, 10, 3)} ${List.tabulate(4)(i => i * i)}")
  println(s"${z.zipWithIndex} ${z.lift(10)} ${z.lift(1)} ${z.collect { case x if x > 4 => x * 10 }} ${z.maxBy(x => (x - 5).abs)}")

Ausgabe:

5 List(3, 9, 1, 7) 7 5 9 List(5, 3) List(1, 7)
List(0, 5, 3, 9, 1, 7) List(5, 3, 9, 1, 7, 100) List(5, 3, 9, 1, 7, 8) List(7, 1, 9, 3, 5) List(1, 3, 5, 7, 9) List(9, 7, 5, 3, 1) List(9, 7, 5, 3, 1)
List(10, 6, 18, 2, 14) List(5, 9, 7) 25 945 1 9 5
true true 5 Some(9) 2 true
25 9 (List(5, 9, 7),List(3, 1)) List((5,a), (3,b), (9,c), (1,d), (7,e)) List(List(5, 3), List(3, 9), List(9, 1), List(1, 7))
List(List(5, 3), List(9, 1), List(7)) List(5, 3, 9) List(1, 7) (List(5, 3, 9),List(1, 7)) (List(5, 3),List(9, 1, 7))
List(1, 2, 3) List(a, b, c, d) List(5, 3, 9, 1, 7) 5, 3, 9, 1, 7 [5;3;9;1;7]
List((1,1), (2,2), (3,3))
List(1, 2, 3) List(0, 1, 3, 6, 10, 15) List(x, x, x) List(0, 3, 6, 9) List(0, 1, 4, 9)
List((5,0), (3,1), (9,2), (1,3), (7,4)) None Some(3) List(50, 90, 70) 9

Maps und Sets

@main def main(): Unit =
  val alter = Map("Mia" -> 17, "Tom" -> 25)
  val mehr = alter + ("Zoe" -> 31)
  val ohne = mehr - "Tom"
  println(s"${alter("Mia")} ${alter.get("Ben")} ${alter.getOrElse("Ben", 0)} ${mehr.size} ${ohne.keys.toList.sorted}")
  println(mehr.toList.sortBy(_._1))
  println(mehr.map((k, v) => (k.toUpperCase, v + 1)).toList.sorted)
  println(mehr.filter((_, v) => v > 20).keys.toList.sorted)
  println(mehr.values.sum)
  for (name, a) <- mehr.toList.sortBy(_._1) do println(s"$name => $a")
 
  val zaehler = "mississippi".groupBy(identity).map((c, s) => c -> s.length)
  println(zaehler.toList.sorted)
  val wort = "ein kleiner langer Satz mit drei".split(" ").toList
  println(wort.groupBy(_.length).toList.sortBy(_._1))
 
  val s = Set(3, 1, 2, 3, 1)
  println(s"${s.size} ${s.contains(2)} ${(s + 9).toList.sorted} ${(s & Set(1, 9)).toList} ${(s | Set(7)).toList.sorted} ${(s -- Set(1)).toList.sorted}")
 
  import scala.collection.mutable
  val veraenderlich = mutable.Map("a" -> 1)
  veraenderlich("b") = 2
  veraenderlich += ("c" -> 3)
  val puffer = mutable.ArrayBuffer(1, 2)
  puffer += 3
  puffer.prepend(0)
  println(s"${veraenderlich.toList.sorted} ${puffer}")

Ausgabe:

17 None 0 3 List(Mia, Zoe)
List((Mia,17), (Tom,25), (Zoe,31))
List((MIA,18), (TOM,26), (ZOE,32))
List(Tom, Zoe)
73
Mia => 17
Tom => 25
Zoe => 31
List((i,4), (m,1), (p,2), (s,4))
List((3,List(ein, mit)), (4,List(Satz, drei)), (6,List(langer)), (7,List(kleiner)))
3 true List(1, 2, 3, 9) List(1) List(1, 2, 3, 7) List(2, 3)
List((a,1), (b,2), (c,3)) ArrayBuffer(0, 1, 2, 3)

Pattern Matching

match zerlegt Werte nach Struktur. Das ist eines der Kernmerkmale von Scala:

case class Punkt(x: Int, y: Int)
 
def beschreibe(wert: Any): String = wert match
  case 0 => "null"
  case n: Int if n < 0 => s"negative Zahl $n"
  case n: Int => s"Zahl $n"
  case s: String if s.isEmpty => "leerer Text"
  case s: String => s"Text mit ${s.length} Zeichen"
  case Punkt(0, 0) => "Ursprung"
  case Punkt(x, 0) => s"auf der x-Achse bei $x"
  case Punkt(x, y) => s"Punkt $x/$y"
  case List() => "leere Liste"
  case List(a) => s"Liste mit einem Element $a"
  case List(a, b, _*) => s"Liste beginnt mit $a, $b"
  case (a, b) => s"Tupel $a, $b"
  case Some(x) => s"Some($x)"
  case None => "None"
  case _ => "unbekannt"
 
def summe(l: List[Int]): Int = l match
  case Nil => 0
  case kopf :: rest => kopf + summe(rest)
 
@main def main(): Unit =
  val tests: List[Any] = List(0, -5, 42, "", "Scala", Punkt(0, 0), Punkt(3, 0), Punkt(1, 2), List(), List(7), List(1, 2, 3), (1, "x"), Some(5), None, 3.5)
  tests.foreach(t => println(beschreibe(t)))
  println(summe(List(1, 2, 3, 4)))
 
  val (a, b) = (1, 2)
  val Punkt(px, py) = Punkt(5, 6)
  val erstes :: zweites :: _ = List(10, 20, 30): @unchecked
  println(s"$a $b $px $py $erstes $zweites")
 
  val ergebnis = List(1, 2, 3, 4, 5, 6).collect:
    case n if n % 2 == 0 => n * n
  println(ergebnis)

Ausgabe:

null
negative Zahl -5
Zahl 42
leerer Text
Text mit 5 Zeichen
Ursprung
auf der x-Achse bei 3
Punkt 1/2
leere Liste
Liste mit einem Element 7
Liste beginnt mit 1, 2
Tupel 1, x
Some(5)
None
unbekannt
10
1 2 5 6 10 20
List(4, 16, 36)

Merke

  • Collections sind unveränderlich: List, Vector, Set, Map; veränderlich in scala.collection.mutable
  • Mächtige Operationen: map, filter, foldLeft, groupBy, zip, sliding, flatMap
  • match mit Mustern: Werte, Typen, case class, Listen, Tupel, Guards (if)
  • Pattern Matching zerlegt auch in val-Definitionen

Übungsaufgabe

Zähle mit groupBy die Wörter eines Satzes und gib die häufigsten aus.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Typen, Kontrollfluss und Funktionen

Weiter: Klassen, Traits und Case Classes

Alle Kapitel: Scala im Überblick