Kotlin Cheatsheet
Basic Syntax
Variable Declaration
val readOnly = 42 // Immutable variable
var mutable = 42 // Mutable variable
Data Types
val number: Int = 42
val decimal: Double = 3.14
val text: String = "Hello, Kotlin!"
val character: Char = 'K'
val flag: Boolean = true
Control Flow
If
Expression
val max = if (a > b) a else b
When
Expression (Switch)
when (value) {
0 -> println("Zero")
1, 2 -> println("One or Two")
in 3..10 -> println("Between 3 and 10")
else -> println("Out of range")
}
For
Loop
for (i in 1..5) { /* ... */ }
for (item in collection) { /* ... */ }
While
Loop
while (condition) { /* ... */ }
do { /* ... */ } while (condition)
Functions
Function Declaration
fun add(a: Int, b: Int): Int {
return a + b
}
// Single-expression function
fun multiply(a: Int, b: Int) = a * b
Default Arguments
fun greet(name: String = "Guest") {
println("Hello, $name!")
}
Named Arguments
greet(name = "Alice")
Higher-Order Functions
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
val sum = operate(3, 4) { x, y -> x + y }
Lambdas and Anonymous Functions
Lambda Expression
val square = { x: Int -> x * x }
val result = square(5) // 25
The it
Keyword
val numbers = listOf(1, 2, 3)
val doubled = numbers.map { it * 2 }
Lambda Syntax
// Basic lambda syntax
val sum = { x: Int, y: Int -> x + y }
val sayHello = { name: String -> println("Hello $name") }
// Lambda with receiver
val isEven: Int.() -> Boolean = { this % 2 == 0 }
// Lambda with implicit parameter 'it'
val square: (Int) -> Int = { it * it }
// Multi-line lambda
val processNumber = { x: Int ->
val doubled = x * 2
doubled + 1
}
Collections
Creating Collections
val list = listOf(1, 2, 3) // Immutable List
val mutableList = mutableListOf(1, 2, 3) // Mutable List
val set = setOf(1, 2, 3) // Immutable Set
val mutableSet = mutableSetOf(1, 2, 3) // Mutable Set
val map = mapOf("a" to 1, "b" to 2) // Immutable Map
val mutableMap = mutableMapOf("a" to 1, "b" to 2) // Mutable Map
Common Collection Operations
map
val squares = numbers.map { it * it }
filter
val evenNumbers = numbers.filter { it % 2 == 0 }
reduce
val sum = numbers.reduce { acc, num -> acc + num }
fold
val product = numbers.fold(1) { acc, num -> acc * num }
any
/ all
/ none
val hasNegative = numbers.any { it < 0 }
val allPositive = numbers.all { it > 0 }
val noneZero = numbers.none { it == 0 }
find
/ firstOrNull
val firstEven = numbers.find { it % 2 == 0 }
groupBy
val grouped = words.groupBy { it.first() }
partition
val (even, odd) = numbers.partition { it % 2 == 0 }
flatMap
val flatList = listOfLists.flatMap { it }
sorted
/ sortedBy
/ sortedDescending
val sortedNumbers = numbers.sorted()
val sortedByLength = words.sortedBy { it.length }
Collection Operations
Transform Operations
// Map transformations
val numbers = listOf(1, 2, 3, 4)
val doubled = numbers.map { it * 2 }
val indexed = numbers.mapIndexed { index, value -> "[$index]: $value" }
val notNull = numbers.mapNotNull { if (it > 2) it else null }
// Flatten operations
val nested = listOf(listOf(1, 2), listOf(3, 4))
val flat = nested.flatten()
val flatMapped = numbers.flatMap { listOf(it, it * 2) }
Filter Operations
// Basic filtering
val filtered = numbers.filter { it > 2 }
val negativeFiltered = numbers.filterNot { it > 2 }
val indexedFilter = numbers.filterIndexed { index, value -> index % 2 == 0 }
// Partitioning
val (evens, odds) = numbers.partition { it % 2 == 0 }
Grouping Operations
// Basic grouping
val grouped = numbers.groupBy { it % 2 }
val groupedWithTransform = numbers.groupBy(
keySelector = { it % 2 },
valueTransform = { "Value: $it" }
)
Aggregation Operations
// Reduction operations
val sum = numbers.reduce { acc, next -> acc + next }
val sumRight = numbers.reduceRight { next, acc -> next + acc }
val sumOrNull = emptyList<Int>().reduceOrNull { acc, next -> acc + next }
// Fold operations
val customSum = numbers.fold(0) { acc, next -> acc + next }
val customSumRight = numbers.foldRight(0) { next, acc -> next + acc }
// Aggregate operations
val count = numbers.count { it % 2 == 0 }
val maxBy = numbers.maxByOrNull { -it }
val sumBy = numbers.sumOf { it * 2 }
Sequence Operations
Creating Sequences
// Different ways to create sequences
val simpleSequence = sequenceOf(1, 2, 3, 4, 5)
val fromCollection = listOf(1, 2, 3).asSequence()
val generated = generateSequence(1) { it + 1 }
val fibonacci = generateSequence(Pair(0, 1)) { Pair(it.second, it.first + it.second) }
.map { it.first }
Sequence Operations
// Efficient chain of operations
val result = numbers.asSequence()
.map { it * 2 }
.filter { it > 5 }
.take(2)
.toList()
// Windowed operations
val windowed = numbers.asSequence()
.windowed(size = 2, step = 1)
.toList()
// Chunked operations
val chunked = numbers.asSequence()
.chunked(2) { it.sum() }
.toList()
String Operations
String Templates
val name = "Kotlin"
println("Hello, $name!")
Substring
val substring = text.substring(0, 5)
Split
val parts = csv.split(",")
Join
val joined = list.joinToString(separator = ",")
Regular Expressions
val regex = "\\d+".toRegex()
val numbers = regex.findAll(text).map { it.value.toInt() }.toList()
Null Safety
Nullable Types
var nullableString: String? = null
Safe Call Operator ?.
val length = nullableString?.length
Elvis Operator ?:
val length = nullableString?.length ?: 0
Not-null Assertion !!
val length = nullableString!!.length // Throws if null
Ranges and Progressions
Ranges
val range = 1..10 // Inclusive range
val exclusiveRange = 1 until 10 // Excludes 10
DownTo
and Step
for (i in 10 downTo 1 step 2) { /* ... */ }
Extension Functions
Defining an Extension Function
fun String.isPalindrome(): Boolean {
return this == this.reversed()
}
val isPalin = "madam".isPalindrome()
Scope Functions
let
val length = nullableString?.let { it.length }
apply
val person = Person().apply {
name = "John"
age = 30
}
also
val numbers = mutableListOf(1, 2, 3).also {
it.add(4)
}
run
val result = nullableString?.run {
length
}
with
val fullName = with(person) {
"$firstName $lastName"
}
// let - useful for nullable objects
nullable?.let { value ->
// use value
}
// with - object configuration
with(object) {
property = value
method()
}
// run - object configuration and computation
object.run {
property = value
method()
computeSomething()
}
// apply - object configuration returning the object
object.apply {
property = value
method()
}
// also - additional effects
object.also { obj ->
// do something with obj
logger.info("Object processed: $obj")
}
Sequences
Creating Sequences
val sequence = sequenceOf(1, 2, 3)
val generatedSequence = generateSequence(1) { it + 1 }
Sequence Operations
val firstTen = generatedSequence.take(10).toList()
Miscellaneous
Destructuring Declarations
val (name, age) = person
Infix Functions
infix fun Int.add(other: Int): Int = this + other
val sum = 2 add 3
Tail Recursive Functions
tailrec fun factorial(n: Int, acc: Int = 1): Int {
return if (n <= 1) acc else factorial(n - 1, acc * n)
}
Operator Overloading
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point) = Point(x + other.x, y + other.y)
}
Common Algorithms
Sorting
val sortedList = unsortedList.sorted()
val sortedByProperty = list.sortedBy { it.property }
Binary Search
val index = sortedList.binarySearch(target)
Finding Max/Min
val max = numbers.maxOrNull()
val min = numbers.minOrNull()
Distinct Elements
val uniqueItems = list.distinct()
Exception Handling
Try-Catch-Finally
try {
// Risky operation
} catch (e: Exception) {
// Handle exception
} finally {
// Cleanup code
}
Higher-Order Functions
// Function that takes a function as parameter
fun operateOnNumber(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}
// Function that returns a function
fun createMultiplier(factor: Int): (Int) -> Int {
return { number -> number * factor }
}
Type-Safe Builders (DSL)
// Example of type-safe builder pattern
class HTML {
fun head(init: Head.() -> Unit) = Head().apply(init)
fun body(init: Body.() -> Unit) = Body().apply(init)
}
class Head {
fun title(init: () -> String) = Title(init())
}
class Body {
fun div(init: Div.() -> Unit) = Div().apply(init)
}
// Usage
html {
head {
title { "Title" }
}
body {
div {
+"Content"
}
}
}
Best Practices & Tips
- Use sequences for large collections when you need multiple operations
- Prefer immutable collections (
listOf
,setOf
,mapOf
) over mutable ones - Use scope functions appropriately based on context:
let
for nullable objectswith
for operating on non-null objectsrun
for object configuration and computing return valueapply
for object configurationalso
for side effects
- Use extension functions to enhance existing classes
- Leverage infix functions for more readable DSLs
- Use typealias for complex function types
Tips for Coding Interviews in Kotlin:
Immutability
: Prefer val over var to promote immutability.Null Safety
: Leverage Kotlin’s null safety features to avoid NullPointerException.Standard Library
: Familiarize yourself with collection operations (map, filter, reduce).Idiomatic Kotlin
: Use extension functions, lambdas, and higher-order functions to write concise code.Readability
: Write clear and readable code; use meaningful names and avoid overly complex expressions.Edge Cases
: Always consider and handle edge cases, such as empty inputs or large datasets.Practice Problems
: Solve algorithm and data structure problems in Kotlin to get comfortable with its features.