Understanding Kotlin Collections
1. Working with Lists
| Method | Description | Example |
|---|---|---|
| listOf() | Creates an immutable list | val numbers = listOf(1, 2, 3, 4) |
| mutableListOf() | Creates a mutable list | val mutableNumbers = mutableListOf(1, 2, 3) |
| add() | Adds an element to a mutable list | mutableNumbers.add(4) |
| remove() | Removes an element from a mutable list | mutableNumbers.remove(2) |
| size | Gets the number of elements in a list | println(numbers.size) |
| get(index) | Gets an element at a specific index | val first = numbers.get(0) |
| indexOf() | Finds the index of an element | val index = numbers.indexOf(3) |
Example: Filtering Lists
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
println(evenNumbers) // [2, 4]
Example: Mapping Lists
val numbers = listOf(1, 2, 3)
val doubled = numbers.map { it * 2 }
println(doubled) // [2, 4, 6]
2. Working with Sets
| Method | Description | Example |
|---|---|---|
| emptySet() | Creates an empty immutable set | val empty = emptySet<String>() |
| setOf() | Creates an immutable set with specified elements | val colors = setOf("red", "green", "blue") |
| mutableSetOf() | Creates a mutable set with specified elements | val numbers = mutableSetOf(1, 2, 3) |
| toSet() | Converts a collection to a set | |
| plus() | Adds an element to a set | |
| minus() | Removes an element from a set | |
Note: Sets in Kotlin are unordered and do not allow duplicate elements.
Example: Set Operations
val setA = setOf(1, 2, 3)
val setB = setOf(3, 4, 5)
// Union
val union = setA + setB // {1, 2, 3, 4, 5}
// Intersection
val intersection = setA intersect setB // {3}
// Difference
val difference = setA subtract setB // {1, 2}
3. Working with Maps
| Method | Description | Example |
|---|---|---|
| mapOf() | Creates an immutable map | val map = mapOf("key1" to "value1", "key2" to "value2") |
| mutableMapOf() | Creates a mutable map | val mutableMap = mutableMapOf("key1" to "value1") |
| get() | Retrieves the value for a key | val value = map["key1"] |
| put() | Adds or updates a key-value pair | mutableMap["key2"] = "value2" |
| remove() | Removes a key-value pair | mutableMap.remove("key1") |
| keys | Returns a set of all keys | val keys = map.keys |
| values | Returns a collection of all values | val values = map.values |
| entries | Returns a set of key-value pairs | for ((key, value) in map.entries) { println("$key = $value") } |
Note: Maps in Kotlin are immutable by default unless created with
mutableMapOf().Warning: Accessing a non-existent key returns
null in Kotlin maps.Map Operations Summary
- Creation: Use
mapOf()for immutable,mutableMapOf()for mutable. - Access: Use
[key]for reading,[key] = valuefor writing. - Iteration: Use
entriesto iterate over key-value pairs.
4. Using Collection Functions
Example: Filtering and Mapping
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenSquares = numbers
.filter { it % 2 == 0 }
.map { it * it }
println(evenSquares) // [4, 16, 36]
| Function | Description | Example |
|---|---|---|
| filter | Returns a list containing only elements that satisfy the predicate | list.filter { it > 5 } |
| map | Transforms each element using the provided function | list.map { it * 2 } |
| flatMap | Maps each element to a collection and flattens the result | list.flatMap { it.split(" ") } |
| find | Returns the first element matching the predicate, or null | list.find { it == 3 } |
| firstOrNull | Returns the first element or null if list is empty | list.firstOrNull() |
| any | Checks if any element satisfies the predicate | list.any { it > 10 } |
| all | Checks if all elements satisfy the predicate | list.all { it > 0 } |
| count | Returns the number of elements matching the predicate | list.count { it % 2 == 0 } |
| groupBy | Groups elements by a key function | list.groupBy { it % 2 } |
| associateBy | Creates a map using a key function | list.associateBy { it.name } |
Note: These functions are
lazy in Kotlin, meaning they don't process elements until the result is consumed.Example: Reducing Collections
val numbers = listOf(1, 2, 3, 4)
val sum = numbers.reduce { acc, value -> acc + value }
println(sum) // 10
val product = numbers.fold(1) { acc, value -> acc * value }
println(product) // 24
| Function | Description | Example |
|---|---|---|
| reduce | Reduces the collection to a single value using a binary operation | list.reduce { a, b -> a + b } |
| fold | Reduces the collection to a single value with an initial accumulator | list.fold(0) { acc, value -> acc + value } |
| sumOf | Computes the sum of a numeric property for each element | list.sumOf { it.value } |
| maxOf | Returns the maximum value of a numeric property | list.maxOf { it.value } |
| minOf | Returns the minimum value of a numeric property | list.minOf { it.value } |
Example: Sorting and Ordering
val numbers = listOf(3, 1, 4, 1, 5)
val sorted = numbers.sorted()
println(sorted) // [1, 1, 3, 4, 5]
val descending = numbers.sortedDescending()
println(descending) // [5, 4, 3, 1, 1]
val byLength = listOf("cat", "elephant", "dog")
.sortedBy { it.length }
println(byLength) // [cat, dog, elephant]
| Function | Description | Example |
|---|---|---|
| sorted | Returns a new list sorted in natural order | list.sorted() |
| sortedDescending | Returns a new list sorted in descending order | list.sortedDescending() |
| sortedBy | Sorts by a property function | list.sortedBy { it.name } |
| sortedByDescending | Sorts by a property function in descending order | list.sortedByDescending { it.name } |
| sortBy | Sorts the list in place (mutable) | list.sortBy { it.name } |
| sortDescendingBy | Sorts the list in place in descending order | list.sortByDescending { it.name } |
5. Iterating Collections
Example: Using forEach to iterate over a list
val numbers = listOf(1, 2, 3, 4, 5)
numbers.forEach { number ->
println(number)
}
| Method | Description | Usage |
|---|---|---|
| forEach | Iterates over each element and executes a block of code | list.forEach { item -> ... } |
| forEachIndexed | Iterates with index access | list.forEachIndexed { index, item -> ... } |
| iterator | Provides an iterator for manual iteration control | val iter = list.iterator() |
Example: Using forEachIndexed to access index and value
val fruits = listOf("apple", "banana", "cherry")
fruits.forEachIndexed { index, fruit ->
println("Fruit at index $index is $fruit")
}
Note:
forEach is the most common and idiomatic way to iterate over collections in Kotlin.6. Transforming Collections
| Method | Description | Example |
|---|---|---|
| map | Transforms each element to a new form | |
| mapNotNull | Transforms each element and filters out nulls | |
| flatMap | Flattens a collection of collections into one | |
| groupBy | Groups elements by a key function | |
| associateBy | Creates a map from elements using a key function | |
Example: Using map and flatMap together
val nestedLists = listOf(listOf(1, 2), listOf(3, 4), listOf(5, 6))
val flatMapped = nestedLists.flatMap { it.map { it * 2 } }
// Result: [2, 4, 6, 8, 10, 12]
7. Searching Collections
| Method | Description | Return Type | Example |
|---|---|---|---|
| find | Returns the first element matching the predicate or null | T? |
|
| findLast | Returns the last element matching the predicate or null | T? |
|
| firstOrNull | Returns the first element or null if collection is empty | T? |
|
| lastOrNull | Returns the last element or null if collection is empty | T? |
|
| any | Checks if any element matches the predicate | Boolean |
|
| all | Checks if all elements match the predicate | Boolean |
|
| none | Checks if no elements match the predicate | Boolean |
|
| count | Counts elements matching the predicate or all if no predicate | Int |
|
Note: These methods return
null for find, firstOrNull, and lastOrNull when no element is found.Search Methods Summary
find: Returns first matching element or nullfindLast: Returns last matching element or nullfirstOrNull: Returns first element or nulllastOrNull: Returns last element or nullany: Checks if any element matches predicateall: Checks if all elements match predicatenone: Checks if no elements match predicatecount: Counts elements matching predicate
8. Sorting Collections
| Method | Description | Return Type | Example |
|---|---|---|---|
| sorted() | Returns a new list with elements sorted in natural order | List<T> |
|
| sortedDescending() | Returns a new list with elements sorted in descending order | List<T> |
|
| sortBy() | Sorts the list in-place by a specified property | Unit |
|
| sortWith() | Sorts the list in-place using a custom comparator | Unit |
|
| sortedBy() | Returns a new list sorted by a specified property | List<T> |
|
| sortedByDescending() | Returns a new list sorted by a specified property in descending order | List<T> |
|
9. Using Sequences for Lazy Evaluation
Sequences in Kotlin provide a way to perform lazy evaluation on collections, which can improve performance by avoiding unnecessary intermediate operations.
| Method | Description | Return Type | Notes |
|---|---|---|---|
| asSequence() | Converts a collection into a sequence. | Sequence<T> |
Used to enable lazy evaluation. |
| map() | Transforms each element of the sequence. | Sequence<R> |
Lazily applied to elements. |
| filter() | Filters elements based on a predicate. | Sequence<T> |
Lazily applied to elements. |
| take() | Take the first n elements of a sequence. | Sequence<T> |
Lazily applied to elements. |
| toList() | Converts the sequence back to a list. | List<T> |
Force evaluation of the sequence. |
Example: Lazy Evaluation with Sequences
val numbers = (1..1000000).asSequence()
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10)
.toList()
println(numbers)
Note: Sequences are particularly useful when chaining multiple operations on large datasets where intermediate collections would be inefficient.
10. Converting Between Collection Types
| Collection Type | Conversion Method | Description |
|---|---|---|
| List<T> | toMutableList() |
Creates a mutable copy of the list |
| List<T> | toSet() |
Converts list to a set, removing duplicates |
| List<T> | toMap() |
Converts list to a map using element as key |
| Set<T> | toList() |
Converts set to a list |
| Set<T> | toMutableList() |
Creates a mutable copy of the set |
| Map<K, V> | keys |
Returns a set of keys from the map |
| Map<K, V> | values |
Returns a collection of values from the map |
Example: Converting List to Set
val list = listOf(1, 2, 2, 3, 4)
val set = list.toSet()
println(set) // Output: [1, 2, 3, 4]
Example: Converting List to Map
val list = listOf("a" to 1, "b" to 2)
val map = list.toMap()
println(map) // Output: {a=1, b=2}
11. Partitioning Collections
| Function | Description | Example | Returns |
|---|---|---|---|
| partition(predicate) | Partitions a collection into two lists based on a predicate. | |
List<T> and List<T> |
| groupBy(keySelector) | Groups elements by a key function into a map. | |
Map<K, List<T>> |
| chunked(size) | Splits a collection into chunks of a specified size. | |
List<List<T>> |
12. Working with Collection Operations
Example: Filtering and Transforming Collections
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenNumbers = numbers.filter { it % 2 == 0 }
val doubledEven = evenNumbers.map { it * 2 }
println(evenNumbers) // [2, 4, 6, 8, 10]
println(doubledEven) // [4, 8, 12, 16, 20]
| Operation | Description | Example |
|---|---|---|
| filter | Returns a list containing only elements that satisfy the predicate | list.filter { it > 5 } |
| map | Transforms each element using the provided function | list.map { it * 2 } |
| flatMap | Flattens a collection of collections into one list | list.flatMap { it.split(" ") } |
| groupBy | Groups elements by a key function into a map | list.groupBy { it.length } |
| fold | Accumulates a value by applying a function to each element | list.fold(0) { acc, i -> acc + i } |
| reduce | Accumulates a value by applying a function to each element (without initial) | list.reduce { acc, i -> acc + i } |
Note:
fold and reduce differ in that fold takes an initial value, while reduce uses the first element as the initial accumulator.