💡 Introduction — Why Kotlin?
Kotlin is a pragmatic, modern language that runs on the JVM, compiles to JavaScript, and supports native targets. It combines concise syntax with strong type safety and excellent interoperability with Java. Kotlin is widely used for Android development, server-side apps (Ktor, Spring), and multiplatform libraries.
This guide covers Kotlin from basics to coroutines and DSA patterns — practical and interview friendly.
🌐 Ecosystem — JVM, Android & Multiplatform
- JVM: Kotlin compiles to bytecode and interops with Java libraries seamlessly.
- Android: Officially supported; Kotlin features reduce boilerplate.
- Multiplatform: Kotlin Multiplatform (KMP) shares code between JVM, JS, and Native.
- Server & Frameworks: Ktor, Spring (Kotlin DSL), Micronaut.
Practical: use Kotlin for both application logic and algorithmic code — concise syntax helps in DSA too.
🛠️ Toolchain & Build
- Gradle Kotlin DSL:
build.gradle.ktsis the common build file. - kotlinc: Kotlin compiler CLI;
javacnot required but used when mixing Java. - IDE support: IntelliJ IDEA has the best Kotlin tooling; Android Studio for Android.
- Packaging: shadowJar, Spring Boot, native images via Kotlin/Native or GraalVM.
🔤 Language Basics & Syntax
Kotlin is statically typed with type inference and expressive syntax.
```
fun main() {
val name: String = "Satish" // immutability by default
var x = 10 // mutable
println("Hello, $name — x = ${x}")
} Prefer val over var for safer code.
⭕ Null Safety & Smart Casts
Kotlin differentiates nullable and non-nullable types at compile time.
```
var s: String? = null // nullable
val len = s?.length ?: 0 // safe call + elvis operator
if (s is String) {
// smart cast — s is non-null String here
println(s.length)
} Use !! sparingly — it throws NPE when you're wrong. Prefer safe operators and clear contracts.
🔁 Functions, Lambdas & Extension Functions
```
fun add(a: Int, b: Int) = a + b
val sq = { x: Int -> x * x } // lambda
fun String.exclaim() = this + "!" // extension
println("hi".exclaim()) // "hi!" Extensions let you add API surface without inheritance — they don't modify original classes (static dispatch).
🏛️ OOP & Data Classes
Kotlin simplifies data containers using data class which auto-generates equals/hashCode/toString/copy.
``` data class Point(val x: Int, val y: Int) val p1 = Point(1,2) val p2 = p1.copy(x = 3) // copy with change println(p1) // Point(x=1, y=2)
Constructors, sealed classes, and object declarations support multiple design styles concisely.
🔬 Advanced Types: Sealed, Inline, Delegation
- Sealed classes: closed hierarchies — great for algebraic data types and exhaustive when branches.
- Inline functions: reduce lambda overhead for high-performance code.
- Delegation:
bykeyword for composition + reuse.
```
sealed class Result
data class Ok(val v: Int): Result()
data class Err(val msg: String): Result()
fun handle(r: Result) = when(r) {
is Ok -> r.v
is Err -> -1
} ⚡ Coroutines & Concurrency
Kotlin coroutines provide structured concurrency and lightweight cooperative threads.
```
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(100)
println("World")
}
println("Hello")
}
// Output: Hello \n World Key primitives: CoroutineScope, launch, async, flow for reactive streams.
📚 Collections & Sequences
Kotlin collections are powerful and come as mutable/immutable views; Sequence is lazy (useful for large pipelines).
```
val list = listOf(1,2,3,4)
val evens = list.filter { it % 2 == 0 }.map { it * it }
val seq = sequenceOf(1,2,3,4).map { heavy(it) }.filter { it%2==0 } // lazy Prefer eager collections for small sets and sequences for large or chained transformations to avoid intermediate allocations.
🎯 DSA-Focused Kotlin Techniques
- Use IntArray / LongArray for primitive performance in tight loops (avoid boxing).
- Use ArrayList (MutableList) for dynamic arrays; prefer
arrayListOf()when mutability needed. - PriorityQueue from Java collections for heaps, or implement your own for custom comparators.
- Use inline functions and
@JvmStaticwhen interoperating with Java for performance-critical hot paths. - For graphs: adjacency lists as
ArrayorArraydepending on mutability/perf.>
Kotlin is concise for DSA: data classes, destructuring, and extension functions speed up implementation without excess boilerplate.
📁 I/O & Competitive Kotlin
For competitive programming, use fast input via buffered reader & tokenizer or custom readers; avoid slow readLine() loops.
```
import java.io.BufferedInputStream
import java.util.StringTokenizer
class FastScanner {
private val input = BufferedInputStream(System.`in`)
private val buffer = ByteArray(1 shl 16)
private var len = 0
private var ptr = 0
private fun read(): Int {
if (ptr >= len) {
len = input.read(buffer)
ptr = 0
if (len <= 0) return -1
}
return buffer[ptr++].toInt()
}
fun next(): String {
val sb = StringBuilder()
var c = read()
while (c <= 32 && c >= 0) c = read()
while (c > 32) {
sb.append(c.toChar()); c = read()
}
return sb.toString()
}
} Alternatively, use java.io.BufferedReader + StringTokenizer for simpler code.
🔗 Java Interop & Platform Types
Kotlin integrates smoothly with Java — call Java APIs natively, but be mindful of platform types and nullability.
``` val list: java.util.List= java.util.ArrayList() list.add("a") // works fine // When calling Java, Kotlin may see types as platform types (nullable/nonnull ambiguous).
Annotate Java APIs with nullability annotations to get safe Kotlin signatures.
🧩 Expanded DSA Examples (Kotlin)
1. Graph — BFS
``` import java.util.ArrayDeque fun bfs(adj: Array```>, start: Int): List { val n = adj.size val vis = BooleanArray(n) val q = ArrayDeque () val order = mutableListOf () vis[start] = true; q.add(start) while (q.isNotEmpty()) { val u = q.removeFirst() order.add(u) for (v in adj[u]) if (!vis[v]) { vis[v] = true; q.add(v) } } return order }
2. Binary Tree — Iterative Inorder
``` class Node(var v: Int, var l: Node? = null, var r: Node? = null) fun inorderIter(root: Node?): List```{ val res = mutableListOf (); val st = ArrayDeque () var curr = root while (curr != null || st.isNotEmpty()) { while (curr != null) { st.addLast(curr); curr = curr.l } curr = st.removeLast() res.add(curr.v) curr = curr.r } return res }
3. Min-Heap (PriorityQueue)
```
import java.util.PriorityQueue
fun kthLargest(arr: IntArray, k: Int): Int {
val pq = PriorityQueue()
for (x in arr) {
pq.add(x)
if (pq.size > k) pq.poll()
}
return pq.peek()
}
```
4. Union-Find (DSU)
```
class DSU(n: Int) {
val p = IntArray(n) { it }
val r = IntArray(n)
fun find(x: Int): Int {
if (p[x] == x) return x
p[x] = find(p[x])
return p[x]
}
fun unite(a: Int, b: Int): Boolean {
var x = find(a); var y = find(b)
if (x == y) return false
if (r[x] < r[y]) { val t = x; x = y; y = t }
p[y] = x
if (r[x] == r[y]) r[x]++
return true
}
}
```
5. Sliding Window Maximum
```
fun maxSlidingWindow(nums: IntArray, k: Int): IntArray {
val dq = ArrayDeque(); val res = mutableListOf()
for (i in nums.indices) {
if (dq.isNotEmpty() && dq.first() == i - k) dq.removeFirst()
while (dq.isNotEmpty() && nums[dq.last()] < nums[i]) dq.removeLast()
dq.addLast(i)
if (i >= k - 1) res.add(nums[dq.first()])
}
return res.toIntArray()
}
```
Practice: prefer primitive arrays for heavy numeric tasks and avoid creating many boxed objects in hot loops.
✅ Best Practices & Common Pitfalls
- Prefer
valfor immutability and clearer intent. - Avoid unnecessary boxing: use
IntArray,LongArraywhen performance matters. - Use coroutines for async flows; cancel scopes properly to avoid leaks.
- Mind platform types when calling Java — add explicit nullability where appropriate.
- Use data classes for DTOs and domain models; be cautious with default values that are mutable.
- Test critical algorithmic code and benchmark with realistic inputs.
🏁 Final Summary — Kotlin Proficiency Checklist
Key topics to master for Kotlin proficiency and DSA readiness:
- Null safety, smart casts, and platform types
- Coroutines and structured concurrency
- Collections, sequences, and primitive arrays for performance
- Data classes, sealed classes, and delegation
- Interoperability with Java and build tooling (Gradle)
- Practical DSA implementations using Kotlin idioms
Next: convert common DSA templates to Kotlin, practice on contests, and build a small Kotlin project that uses coroutines and Ktor.