thecodex.expert · The Codex Family of Knowledge
Snippets

Kotlin Snippets

13 idiomatic Kotlin patterns — copy, paste, adapt.

Kotlin 2.x 13 snippets Verified
Kotlindata_classes.kt
Data classes: copy, destructuring, and component functions
data class User(
    val id: Int,
    val name: String,
    val email: String,
    val active: Boolean = true
)

fun main() {
    val alice = User(1, "Alice", "alice@example.com")
    println(alice)        // User(id=1, name=Alice, email=alice@example.com, active=true)
    
    // copy: create modified version without mutation
    val updated = alice.copy(email = "newalice@example.com", active = false)
    println(updated.email)  // newalice@example.com
    println(alice.email)    // alice@example.com — unchanged
    
    // equals: structural comparison (not reference)
    val alice2 = User(1, "Alice", "alice@example.com")
    println(alice == alice2)   // true — content-based
    println(alice === alice2)  // false — different objects
    
    // Destructuring
    val (id, name, email) = alice
    println("$name ($email)")  // Alice (alice@example.com)
    
    // Destructuring in for loop
    val users = listOf(alice, updated)
    for ((_, n, e) in users) {  // _ ignores id
        println("$n: $e")
    }
}
Kotlinnull_safety.kt
Null safety: ?., ?:, let, and smart casts
fun findUser(id: Int): String? = if (id > 0) "User$id" else null

fun main() {
    val name: String? = findUser(1)
    
    // Safe call: returns null if receiver is null
    println(name?.length)         // 5
    println(name?.uppercase())    // USER1
    
    // Elvis operator: default when null
    val display = name ?: "Unknown"  // "User1"
    val empty = findUser(-1) ?: "Anonymous"  // "Anonymous"
    
    // Chain: short-circuits at first null
    val nested: String? = null
    val len = nested?.trim()?.length  // null (no exception)
    
    // let: run block only when non-null
    name?.let { n ->
        println("Processing: $n")  // runs
    }
    findUser(-1)?.let {
        println("won't print")  // doesn't run
    }
    
    // Smart cast: after null check, no ?. needed
    if (name != null) {
        println(name.length)    // name is String here (not String?)
        println(name.uppercase())
    }
    
    // requireNotNull: fail fast with message
    val required: String? = "value"
    val notNull: String = requireNotNull(required) { "name is required" }
}
Kotlinscope_functions.kt
Scope functions: let, run, apply, also, with
data class Config(var host: String = "", var port: Int = 0, var debug: Boolean = false)

fun main() {
    // apply: configure object, returns the object (this inside)
    val config = Config().apply {
        host = "localhost"
        port = 8080
        debug = true
    }
    println(config)  // Config(host=localhost, port=8080, debug=true)
    
    // also: side effect (logging/validation), returns the object (it inside)
    val validated = config
        .also { require(it.port > 0) { "Port must be positive" } }
        .also { println("Config validated: $it") }
    
    // let: transform value, returns lambda result (it inside)
    val greeting = "Alice"?.let { "Hello, $it!" } ?: "Hello!"
    
    // run: compute value, returns lambda result (this inside)
    val summary = config.run {
        "Server at $host:$port (debug=$debug)"
    }
    println(summary)
    
    // with: non-extension version of run — pass object as argument
    val description = with(config) {
        buildString {
            append("Host: $host\n")
            append("Port: $port\n")
            append("Debug: $debug\n")
        }
    }
    println(description)
}
Kotlincollections.kt
Collections: filter, map, groupBy, flatMap
data class Person(val name: String, val age: Int, val city: String)

fun main() {
    val people = listOf(
        Person("Alice", 30, "Mumbai"),
        Person("Bob", 25, "Delhi"),
        Person("Carol", 35, "Mumbai"),
        Person("Dave", 28, "Bangalore")
    )
    
    // filter + map + sorted
    val mumbaites = people
        .filter { it.city == "Mumbai" }
        .sortedBy { it.age }
        .map { it.name }
    println(mumbaites)  // [Alice, Carol]
    
    // groupBy: Map<K, List<V>>
    val byCity = people.groupBy { it.city }
    byCity.forEach { (city, residents) ->
        println("$city: ${residents.map { it.name }}")
    }
    
    // associate: build a map
    val ageMap = people.associateBy({ it.name }, { it.age })
    println(ageMap["Alice"])  // 30
    
    // flatMap: flatten
    val hobbies = mapOf("Alice" to listOf("coding","reading"), "Bob" to listOf("gaming"))
    val allHobbies = hobbies.values.flatten()
    
    // partition: split into two lists
    val (seniors, juniors) = people.partition { it.age >= 30 }
    println(seniors.map { it.name })  // [Alice, Carol]
    
    // fold: accumulate
    val totalAge = people.fold(0) { acc, p -> acc + p.age }
    
    // zip: pair two collections
    val names = listOf("A", "B", "C")
    val scores = listOf(1, 2, 3)
    val paired = names.zip(scores)  // [(A,1),(B,2),(C,3)]
}
Kotlinsealed_classes.kt
Sealed classes for typed results
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val code: Int, val message: String) : Result<Nothing>()
    data object Loading : Result<Nothing>()
}

fun fetchUser(id: Int): Result<String> = when {
    id <= 0  -> Result.Error(400, "Invalid ID")
    id > 100 -> Result.Error(404, "User not found")
    else     -> Result.Success("User$id")
}

fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println("Got: ${result.data}")
        is Result.Error   -> println("Error ${result.code}: ${result.message}")
        Result.Loading    -> println("Loading...")
        // Compiler warns if any case is missing
    }
}

// Sealed interface: allows multiple inheritance
sealed interface UiEvent
data class Navigate(val route: String) : UiEvent
data class ShowSnackbar(val message: String) : UiEvent
data object HideKeyboard : UiEvent

fun main() {
    handleResult(fetchUser(42))    // Got: User42
    handleResult(fetchUser(-1))    // Error 400: Invalid ID
    handleResult(Result.Loading)   // Loading...
    
    val event: UiEvent = Navigate("/home")
    val message = when (event) {
        is Navigate      -> "Navigating to ${event.route}"
        is ShowSnackbar  -> "Showing: ${event.message}"
        HideKeyboard     -> "Hiding keyboard"
    }
    println(message)
}
Kotlinextension_functions.kt
Extension functions and properties
// Extension functions: add methods to existing types without inheritance
fun String.isValidEmail(): Boolean = contains("@") && contains(".")
fun String.truncate(max: Int, suffix: String = "...") =
    if (length <= max) this else take(max - suffix.length) + suffix
fun Int.isEven(): Boolean = this % 2 == 0
fun <T> List<T>.second(): T = this[1]

// Extension property
val String.wordCount: Int get() = if (isBlank()) 0 else trim().split(Regex("\\s+")).size

// Nullable receiver extension
fun String?.orEmpty(): String = this ?: ""

// Extension on generic type
fun <T> List<T>.forEachIndexedReversed(action: (Int, T) -> Unit) {
    for (i in lastIndex downTo 0) action(i, this[i])
}

fun main() {
    println("alice@example.com".isValidEmail())   // true
    println("Hello, this is a long string".truncate(15))  // "Hello, this ..."
    println(4.isEven())  // true
    
    val words = "Hello Kotlin World"
    println(words.wordCount)  // 3
    
    val null_str: String? = null
    println(null_str.orEmpty())  // ""
    
    listOf("a", "b", "c").forEachIndexedReversed { i, s ->
        print("$i:$s ")  // 2:c 1:b 0:a
    }
    
    // Extension functions resolve statically — not virtual
    open class Base
    class Derived : Base()
    fun Base.greet() = "Base"
    fun Derived.greet() = "Derived"
    
    val b: Base = Derived()
    println(b.greet())  // "Base" — static dispatch, not "Derived"
}
Kotlincoroutines.kt
Coroutines: launch, async, and structured concurrency
import kotlinx.coroutines.*

suspend fun fetchUser(id: Int): String {
    delay(100)   // non-blocking — frees the thread
    return "User$id"
}

suspend fun fetchPosts(userId: String): List<String> {
    delay(150)
    return listOf("Post1 by $userId", "Post2 by $userId")
}

fun main() = runBlocking {
    // Sequential: total ~250ms
    val u1 = fetchUser(1)
    val p1 = fetchPosts(u1)
    println("$u1: $p1")
    
    // Concurrent with async: total ~150ms (both start at once)
    val userDeferred  = async { fetchUser(2) }
    val postsDeferred = async { fetchPosts("User2") }
    val u2 = userDeferred.await()
    val p2 = postsDeferred.await()
    println("$u2: $p2")
    
    // coroutineScope: structured concurrency — cancels children on failure
    val result = coroutineScope {
        val a = async { fetchUser(3) }
        val b = async { fetchUser(4) }
        "${a.await()} and ${b.await()}"
    }
    println(result)
    
    // withContext: switch dispatcher for blocking work
    val data = withContext(Dispatchers.IO) {
        // Safe to block here — IO thread pool
        Thread.sleep(10)
        "data from disk"
    }
    println(data)
}
Kotlinflow.kt
Flow: cold streams and StateFlow
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// Cold flow: producer only runs when collected
fun numbers(): Flow<Int> = flow {
    for (i in 1..5) {
        delay(100)
        emit(i)
    }
}

fun main() = runBlocking {
    // Collect with operators
    numbers()
        .filter { it % 2 == 0 }
        .map { it * it }
        .collect { println(it) }  // 4, 16
    
    // StateFlow: hot flow — always has current value
    val counter = MutableStateFlow(0)
    
    val job = launch {
        counter.collect { println("Counter: $it") }  // prints each emission
    }
    
    repeat(3) {
        delay(100)
        counter.value++
    }
    job.cancel()
    
    // transform: more powerful than map — can emit multiple values
    val doubled = numbers()
        .transform { value ->
            emit(value)
            emit(value * 2)  // emit twice per input
        }
        .take(6)
        .toList()
    println(doubled)  // [1, 2, 2, 4, 3, 6]
    
    // catch: error handling in flow
    flow<Int> { emit(1); throw RuntimeException("oops") }
        .catch { e -> println("Caught: ${e.message}") }
        .collect { println(it) }
}
Kotlindelegation.kt
Delegation: by lazy, by Delegates, and interface delegation
import kotlin.properties.Delegates

class HeavyResource {
    init { println("HeavyResource created") }
    fun use() = "using resource"
}

class MyService(private val logger: Logger) : Logger by logger {
    // Delegates all Logger methods to logger — no boilerplate
}

interface Logger {
    fun log(msg: String)
    fun error(msg: String)
}

class ConsoleLogger : Logger {
    override fun log(msg: String)   = println("[LOG] $msg")
    override fun error(msg: String) = println("[ERR] $msg")
}

fun main() {
    // by lazy: computed once on first access, then cached
    val resource by lazy {
        println("Initialising...")
        HeavyResource()
    }
    println("Before access")
    println(resource.use())  // "Initialising..." then "using resource"
    println(resource.use())  // just "using resource" — already computed
    
    // by Delegates.observable: fire callback on change
    var watched by Delegates.observable("initial") { prop, old, new ->
        println("${prop.name} changed: $old → $new")
    }
    watched = "updated"   // "watched changed: initial → updated"
    
    // by Delegates.vetoable: reject changes
    var positive by Delegates.vetoable(0) { _, _, new -> new >= 0 }
    positive = 5    // accepted
    positive = -1   // rejected — value stays 5
    println(positive)  // 5
    
    // Interface delegation
    val service = MyService(ConsoleLogger())
    service.log("Hello")   // [LOG] Hello
}
Kotlingenerics.kt
Generics, variance, and reified type parameters
// Generic class with constraint
class SortedList<T : Comparable<T>> {
    private val items = mutableListOf<T>()
    fun add(item: T) { items.add(item); items.sort() }
    fun toList(): List<T> = items.toList()
}

// Covariant: out T — produces T, never consumes
class Box<out T>(val value: T)  // Box<String> can be used as Box<Any>

// Contravariant: in T — consumes T, never produces
class Sorter<in T : Comparable<T>> {
    fun sort(items: MutableList<T>) = items.sort()
}

// Reified: access type T at runtime in inline functions
inline fun <reified T> List<*>.filterIsInstance(): List<T> =
    filter { it is T }.map { it as T }

inline fun <reified T> String.parseAs(): T? = try {
    when (T::class) {
        Int::class    -> toInt() as T
        Double::class -> toDouble() as T
        else          -> null
    }
} catch (e: NumberFormatException) { null }

fun main() {
    val sorted = SortedList<Int>()
    sorted.add(5); sorted.add(2); sorted.add(8)
    println(sorted.toList())  // [2, 5, 8]
    
    val mixed: List<Any> = listOf(1, "hello", 2, "world", 3)
    val ints: List<Int> = mixed.filterIsInstance()
    println(ints)  // [1, 2, 3]
    
    val n: Int? = "42".parseAs()
    println(n)  // 42
}
Kotlinstring_templates.kt
String templates, multiline strings, and buildString
fun main() {
    val name = "Alice"
    val score = 95
    
    // String templates: $variable and ${expression}
    println("$name scored $score")
    println("$name scored ${score * 2} doubled")
    println("${name.uppercase()} — ${if (score >= 90) "Excellent" else "Good"}")
    
    // Triple-quoted multiline string
    val json = """
        {
            "name": "$name",
            "score": $score
        }
    """.trimIndent()  // removes leading indentation
    println(json)
    
    // Raw string: no escaping needed
    val regex = """^\d{3}-\d{4}$"""  // no need to escape backslashes
    
    // buildString: efficient string construction
    val report = buildString {
        appendLine("=== Report ===")
        repeat(3) { i -> appendLine("  Item $i: ${i * 10}") }
        append("Total: 30")
    }
    println(report)
    
    // String operations
    "  hello world  ".trim()                    // "hello world"
    "a,b,c,d".split(",")                        // [a, b, c, d]
    listOf("one","two","three").joinToString(" | ")  // "one | two | three"
    "abc".padStart(6, '0')                      // "000abc"
}
Kotlincompanion_object.kt
Companion objects and object declarations
class Currency private constructor(
    val amount: Double,
    val code: String
) {
    companion object {  // like static methods/fields in Java
        val USD = Currency(1.0, "USD")
        val EUR = Currency(0.92, "EUR")
        
        fun of(amount: Double, code: String): Currency {
            require(amount >= 0) { "Amount must be non-negative" }
            return Currency(amount, code)
        }
        
        // @JvmStatic: makes callable as static from Java
        @JvmStatic
        fun parse(s: String): Currency {
            val (amount, code) = s.split(" ")
            return Currency(amount.toDouble(), code)
        }
    }
    
    operator fun plus(other: Currency): Currency {
        require(code == other.code) { "Currency mismatch" }
        return Currency(amount + other.amount, code)
    }
    
    override fun toString() = "$amount $code"
}

// Object declaration: singleton
object Database {
    private var connected = false
    fun connect() { connected = true; println("Connected") }
    fun isConnected() = connected
}

fun main() {
    val price = Currency.of(29.99, "USD")
    val tax = Currency.of(2.40, "USD")
    println(price + tax)  // 32.39 USD
    
    Database.connect()
    println(Database.isConnected())  // true
}
Kotlindsl_builder.kt
Type-safe DSL builder with lambda with receiver
// Lambda with receiver: T.() -> Unit — enables DSL syntax
@DslMarker annotation class HtmlDsl

@HtmlDsl
class Tag(val name: String) {
    private val attrs = mutableMapOf<String, String>()
    private val children = mutableListOf<Tag>()
    var text: String? = null
    
    fun attr(key: String, value: String) { attrs[key] = value }
    
    fun tag(name: String, init: Tag.() -> Unit): Tag {
        val child = Tag(name).apply(init)
        children.add(child)
        return child
    }
    
    fun render(indent: Int = 0): String = buildString {
        val pad = "  ".repeat(indent)
        val attrStr = attrs.entries.joinToString(" ") { (k,v) -> """$k="$v"""" }
        append("$pad<$name${if (attrStr.isNotEmpty()) " $attrStr" else ""}>\n")
        text?.let { append("$pad  $it\n") }
        children.forEach { append(it.render(indent + 1)) }
        append("$pad</$name>\n")
    }
}

fun html(init: Tag.() -> Unit) = Tag("html").apply(init)

fun main() {
    val page = html {
        tag("head") {
            tag("title") { text = "My Page" }
        }
        tag("body") {
            tag("h1") { text = "Hello, Kotlin!" }
            tag("p") {
                attr("class", "intro")
                text = "DSL built with lambdas."
            }
        }
    }
    println(page.render())
}
Kotlin referenceKotlin overview · Learn Kotlin
← C++ Swift snippets →
Everything Kotlin in one place — learning paths, reference, playground, and more. Kotlin Hub →