Iterable.filterIsInstance în Kotlin

Păstrează doar elementele de un anumit tip și întoarce o listă cu acel tip.

Sintaxă
inline fun <reified R> Iterable<*>.filterIsInstance(): List<R>

Ce face Iterable.filterIsInstance

Când o listă conține obiecte de tipuri diferite (de exemplu List<Any> sau o listă de forme geometrice cu clase diferite), filterIsInstance<Tip>() le păstrează doar pe cele de tipul cerut. Rezultatul are direct tipul List<Tip>, deci poți folosi proprietățile lui fără conversii.

Verificarea este aceeași ca la is: un obiect al unei subclase trece și el. Tipul se scrie între <>; funcția este inline cu tip reified, de aceea tipul este cunoscut la rulare.

Parametri

Parametru Descriere
R Tipul elementelor de păstrat.

Ce returnează

O List<R> cu elementele de tipul R.

Exemple

Exemplul 1: Valori amestecate

Din aceeași listă extragem numerele întregi și textele.

fun main() {
    val valori: List<Any> = listOf("Iași", 42, 3.14, "Cluj", 7, true)
    val intregi = valori.filterIsInstance<Int>()
    val texte = valori.filterIsInstance<String>()
    println("Întregi: $intregi, suma ${intregi.sum()}")
    println("Texte: $texte")
}

Rezultat

Întregi: [42, 7], suma 49
Texte: [Iași, Cluj]

Exemplul 2: Notificări de tipuri diferite

Dintr-o listă de notificări (interfață comună) alegem doar comenzile, ca să adunăm valoarea lor.

sealed interface Notificare
data class Mesaj(val de: String, val text: String) : Notificare
data class Comanda(val numar: Int, val valoare: Double) : Notificare
data class Sistem(val info: String) : Notificare

fun main() {
    val notificari = listOf(
        Mesaj("Ana", "Bună!"),
        Comanda(101, 250.0),
        Sistem("Actualizare disponibilă"),
        Comanda(102, 99.9),
    )
    val comenzi = notificari.filterIsInstance<Comanda>()
    println("Comenzi: ${comenzi.map { it.numar }}")
    println("Valoare totală: ${comenzi.sumOf { it.valoare }} lei")
}

Rezultat

Comenzi: [101, 102]
Valoare totală: 349.9 lei

Greșeli frecvente

  • Scrii filter { it is Int }: elementele sunt filtrate, dar tipul listei rămâne List<Any>. filterIsInstance<Int>() dă List<Int>.
  • Te aștepți ca filterIsInstance<List<String>>() să verifice tipul elementelor din liste: la rulare tipurile generice sunt șterse, se verifică doar că obiectul este o List.

Comenzi înrudite

  • Iterable.filter: Creează o listă nouă doar cu elementele care îndeplinesc condiția (filterNot: cu cele care nu o îndeplinesc).
  • Iterable.filterNotNull: Întoarce o listă nouă fără elementele null; tipul rezultatului nu mai permite null.
  • Iterable.mapNotNull: Aplică o funcție fiecărui element și păstrează doar rezultatele care nu sunt null; firstNotNullOf întoarce primul astfel de rezultat.