EMZETT.
Login

Kurz: Kotlin unterscheidet schreibgeschützte (List, Set, Map) und veränderbare (MutableList …) Collections.

Teil des Kurses Kotlin

Kapitel 6 von 13 im Kurs Kotlin (Abschnitt „Collections“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Listen

Kotlin unterscheidet schreibgeschützte (List, Set, Map) und veränderbare (MutableList …) Collections.

fun main() {
    val feste = listOf("Apfel", "Birne", "Kirsche")      // nicht veränderbar
    val liste = mutableListOf(5, 3, 9)
    liste.add(1)
    liste.add(0, 42)
    liste.remove(9)
    liste[1] = 7
    println("$feste ${feste.size} ${feste[0]} ${feste.first()} ${feste.last()}")
    println(liste)
    println(liste.sorted())
    println(liste.sortedDescending())
    println(liste.reversed())
    println(liste.contains(7))
    println(7 in liste)
    println(liste.indexOf(7))
    println(liste.getOrNull(10))
    println(liste.subList(1, 3))
    println(liste + listOf(100))
    println(liste - 7)
    println(emptyList<Int>().isEmpty())
    for ((i, x) in liste.withIndex()) print("$i:$x ")
    println()
}

Ausgabe:

[Apfel, Birne, Kirsche] 3 Apfel Apfel Kirsche
[42, 7, 3, 1]
[1, 3, 7, 42]
[42, 7, 3, 1]
[1, 3, 7, 42]
true
true
1
null
[7, 3]
[42, 7, 3, 1, 100]
[42, 3, 1]
true
0:42 1:7 2:3 3:1

Sets und Maps

fun main() {
    val s = mutableSetOf(3, 1, 3, 2)
    s.add(2); s.add(9)
    println("$s ${s.size} ${5 in s}")
    println(setOf(1, 2, 3) intersect setOf(2, 3, 4))
    println(setOf(1, 2, 3) union setOf(2, 3, 4))
    println(setOf(1, 2, 3) subtract setOf(2))
 
    val m = mutableMapOf("a" to 1, "b" to 2)
    m["c"] = 3
    m.put("a", 10)
    println(m)
    println("${m["a"]} ${m["x"]} ${m.getOrDefault("x", 0)} ${m.getOrElse("y") { -1 }}")
    println("${m.keys} ${m.values} ${m.size} ${m.containsKey("b")}")
    m.remove("b")
    for ((k, v) in m) print("$k=$v ")
    println()
    println(m.mapValues { it.value * 2 })
    println(m.filter { it.value > 5 })
    println(m.toList())
    val zaehler = mutableMapOf<Char, Int>()
    for (c in "mississippi") zaehler[c] = (zaehler[c] ?: 0) + 1
    println(zaehler)
}

Ausgabe:

[3, 1, 2, 9] 4 false
[2, 3]
[1, 2, 3, 4]
[1, 3]
{a=10, b=2, c=3}
10 null 0 -1
[a, b, c] [10, 2, 3] 3 true
a=10 c=3
{a=20, c=6}
{a=10}
[(a, 10), (c, 3)]
{m=1, i=4, s=4, p=2}

map, filter, reduce und mehr

Hier zeigt sich Kotlins Stärke: Collections lassen sich mit wenigen Funktionen umformen.

data class Mensch(val name: String, val alter: Int, val stadt: String)
 
fun main() {
    val z = listOf(1, 2, 3, 4, 5, 6)
    println(z.map { it * it })
    println(z.filter { it % 2 == 0 })
    println(z.reduce { a, b -> a + b })
    println(z.fold(100) { a, b -> a - b })
    println("${z.sum()} ${z.count { it > 3 }} ${z.any { it > 5 }} ${z.all { it > 0 }} ${z.none { it > 9 }}")
    println(z.take(2))
    println(z.drop(4))
    println(z.takeWhile { it < 4 })
    println(z.partition { it > 3 })
    println(z.chunked(4))
    println(z.windowed(3))
    println(z.zip(listOf("a", "b", "c")))
    println(z.find { it > 3 })
    println(z.firstOrNull { it > 10 })
    println(listOf(listOf(1, 2), listOf(3)).flatten())
    println(listOf("ab", "cd").flatMap { it.toList() })
    println(listOf(1, 2, 2, 3, 3, 3).distinct())
    println(listOf("x", "y").joinToString(prefix = "[", postfix = "]", separator = "; "))
 
    val leute = listOf(Mensch("Mia", 17, "Berlin"), Mensch("Tom", 25, "Hamburg"),
                       Mensch("Zoe", 31, "Berlin"), Mensch("Ben", 25, "Köln"))
    println(leute.groupBy { it.stadt }.mapValues { e -> e.value.map { it.name } })
    println(leute.sortedBy { it.alter }.map { it.name })
    println(leute.sortedWith(compareBy({ -it.alter }, { it.name })).map { it.name })
    println(leute.maxBy { it.alter }?.name)
    println(leute.map { it.alter }.average())
    println(leute.associateBy { it.name }.keys)
    println(leute.associate { it.name to it.alter })
    println(leute.groupingBy { it.stadt }.eachCount())
}

Ausgabe:

[1, 4, 9, 16, 25, 36]
[2, 4, 6]
21
79
21 3 true true true
[1, 2]
[5, 6]
[1, 2, 3]
([4, 5, 6], [1, 2, 3])
[[1, 2, 3, 4], [5, 6]]
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
[(1, a), (2, b), (3, c)]
4
null
[1, 2, 3]
[a, b, c, d]
[1, 2, 3]
[x; y]
{Berlin=[Mia, Zoe], Hamburg=[Tom], Köln=[Ben]}
[Mia, Tom, Ben, Zoe]
[Zoe, Ben, Tom, Mia]
Zoe
24.5
[Mia, Tom, Zoe, Ben]
{Mia=17, Tom=25, Zoe=31, Ben=25}
{Berlin=2, Hamburg=1, Köln=1}

Sequenzen: faul statt sofort

Collection-Ketten erzeugen Zwischenlisten. asSequence() verarbeitet Element für Element (lazy), gut für große oder unendliche Folgen:

fun main() {
    val ergebnis = (1..1_000_000).asSequence()
        .filter { it % 3 == 0 }
        .map { it * 2 }
        .take(5)
        .toList()
    println(ergebnis)
 
    val fib = generateSequence(Pair(0, 1)) { Pair(it.second, it.first + it.second) }.map { it.first }
    println(fib.take(10).toList())
 
    val s = sequence {
        yield(1)
        yield(2)
        yieldAll(listOf(3, 4))
    }
    println(s.toList())
}

Ausgabe:

[6, 12, 18, 24, 30]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
[1, 2, 3, 4]

Arrays

fun main() {
    val a = intArrayOf(5, 2, 8)
    a[0] = 1
    a.sort()
    println(a.joinToString())
    val b = Array(3) { i -> i * i }
    println(b.toList())
    println(arrayOf("x", "y").size)
    println(a.sum())
}

Ausgabe:

1, 2, 8
[0, 1, 4]
2
11

Merke

  • listOf/setOf/mapOf (fest) und mutableListOf … (veränderbar)
  • Maps: m["k"], to, for ((k, v) in m)
  • map, filter, reduce, fold, groupBy, sortedBy, zip, flatMap, associate
  • asSequence() für lazy Verarbeitung
  • Arrays (IntArray, Array<T>) für feste Größe und Leistung

Übungsaufgabe

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

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Null-Sicherheit

Weiter: Klassen und Objekte

Alle Kapitel: Kotlin im Überblick