Basic Syntax
Variable Declaration
val readOnly = 42 // Immutable variablevar mutable = 42 // Mutable variableData Types
val number: Int = 42val decimal: Double = 3.14val text: String = "Hello, Kotlin!"val character: Char = 'K'val flag: Boolean = trueControl Flow
If Expression
val max = if (a > b) a else bWhen 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 functionfun multiply(a: Int, b: Int) = a * bDefault 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) // 25The it Keyword
val numbers = listOf(1, 2, 3)val doubled = numbers.map { it * 2 }Lambda Syntax
// Basic lambda syntaxval sum = { x: Int, y: Int -> x + y }val sayHello = { name: String -> println("Hello $name") }
// Lambda with receiverval isEven: Int.() -> Boolean = { this % 2 == 0 }
// Lambda with implicit parameter 'it'val square: (Int) -> Int = { it * it }
// Multi-line lambdaval processNumber = { x: Int -> val doubled = x * 2 doubled + 1}Collections
Creating Collections
val list = listOf(1, 2, 3) // Immutable Listval mutableList = mutableListOf(1, 2, 3) // Mutable List
val set = setOf(1, 2, 3) // Immutable Setval mutableSet = mutableSetOf(1, 2, 3) // Mutable Set
val map = mapOf("a" to 1, "b" to 2) // Immutable Mapval mutableMap = mutableMapOf("a" to 1, "b" to 2) // Mutable MapCommon 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 transformationsval 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 operationsval nested = listOf(listOf(1, 2), listOf(3, 4))val flat = nested.flatten()val flatMapped = numbers.flatMap { listOf(it, it * 2) }Filter Operations
// Basic filteringval filtered = numbers.filter { it > 2 }val negativeFiltered = numbers.filterNot { it > 2 }val indexedFilter = numbers.filterIndexed { index, value -> index % 2 == 0 }
// Partitioningval (evens, odds) = numbers.partition { it % 2 == 0 }Grouping Operations
// Basic groupingval grouped = numbers.groupBy { it % 2 }val groupedWithTransform = numbers.groupBy( keySelector = { it % 2 }, valueTransform = { "Value: $it" })Aggregation Operations
// Reduction operationsval 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 operationsval customSum = numbers.fold(0) { acc, next -> acc + next }val customSumRight = numbers.foldRight(0) { next, acc -> next + acc }
// Aggregate operationsval 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 sequencesval 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 operationsval result = numbers.asSequence() .map { it * 2 } .filter { it > 5 } .take(2) .toList()
// Windowed operationsval windowed = numbers.asSequence() .windowed(size = 2, step = 1) .toList()
// Chunked operationsval 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? = nullSafe Call Operator ?.
val length = nullableString?.lengthElvis Operator ?:
val length = nullableString?.length ?: 0Not-null Assertion !!
val length = nullableString!!.length // Throws if nullRanges and Progressions
Ranges
val range = 1..10 // Inclusive rangeval exclusiveRange = 1 until 10 // Excludes 10DownTo 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 objectsnullable?.let { value -> // use value}
// with - object configurationwith(object) { property = value method()}
// run - object configuration and computationobject.run { property = value method() computeSomething()}
// apply - object configuration returning the objectobject.apply { property = value method()}
// also - additional effectsobject.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) = personInfix Functions
infix fun Int.add(other: Int): Int = this + otherval sum = 2 add 3Tail 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 parameterfun operateOnNumber(x: Int, operation: (Int) -> Int): Int { return operation(x)}
// Function that returns a functionfun createMultiplier(factor: Int): (Int) -> Int { return { number -> number * factor }}Type-Safe Builders (DSL)
// Example of type-safe builder patternclass 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)}
// Usagehtml { 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:
letfor nullable objectswithfor operating on non-null objectsrunfor object configuration and computing return valueapplyfor object configurationalsofor 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.