Kotlin provides a rich set of tools for working with collections like lists, sets, and maps. Whether you want to add, remove, sort, filter, or transform data, Kotlin’s standard library makes it easy and expressive.
Two Ways Kotlin Defines Collection Functions
Collection operations are declared in two ways:
- Member functions
- Extension functions
Member functions:
These are built directly into the collection types. For example:
- isEmpty() checks if a collection has no elements.
- get(index) retrieves an item from a list at a given index.
These are core operations that every collection type should support. If you’re building your own custom collection class, you’ll need to implement these yourself. To make that easier, Kotlin gives you helper classes like AbstractList, AbstractSet, and AbstractMap that provide basic behavior out of the box.
Extension function:
Most other helpful collection operations like filter(), map(), sorted(), etc. are implemented as extension functions. These let you add new behavior to existing classes without modifying them. These functions work for both mutable (can change) and read-only (cannot change) collections.
Operations of Kotlin Collections
Kotlin offers a long list of powerful operations you can use on collections. Here are the main types of operations you’ll often use:
- Transformations - Change the contents of the collection, like converting all items to uppercase using map().
- Filtering - Pick only the elements that match a certain condition using filter() or filterNot().
- Combining with + and – operators - Use the + operator to add elements to a collection, or the – operator to remove them. These always return a new collection.
- Grouping - Group elements by a property, for example, groupBy { it.length } to group words by length.
- Retrieving collection parts - Get only a part of a collection using functions like take(), drop(), slice(), etc.
- Retrieving single elements - Use functions like first(), last(), or find() to retrieve a single element.
- Ordering - Sort collections using sorted(), sortedBy(), or shuffle items using shuffled().
- Aggregate operations - Count items, calculate sums, averages, or check conditions using count(), sum(), any(), all(), and more.
All the operations discussed above return their results without affecting the original content of the collection. For example, when we apply to filter operation then it produces a new collection that contains all the elements matching the filtering predicate. Results of these operations should be either stored in variables or could be passed to other functions.
Kotlin program using filter operation:
fun main() {
val str = mutableListOf("Geeks", "for", "Geeks", "A", "Computer", "Portal")
// original collection remains same
str.filter { it.length > 4 }
println("Original collection elements still unchanged $str")
// result is stored in newStr
val newStr = str.filter { it.length > 4 }
println("New Collection obtains after filtering $newStr")
}
Output:
Original collection elements still unchanged [Geeks, for, Geeks, A, Computer, Portal]
New Collection obtains after filtering [Geeks, Geeks, Computer, Portal]
For limited collection operations, we can specify the destination object and it is optional. Destination should be mutable collection to which the function add its resulting items instead of returning them in a new object. To perform these operations with destinations, we can separate functions with the To postfix notation in their names, for example, use filterTo() instead of filter().
Kotlin program of using destination object:
fun main() {
val str = listOf("Geeks", "for", "Geeks", "A", "Computer", "Portal")
//destination object
val filterResults = mutableListOf<String>()
str.filterTo(filterResults) { it.length > 5 }
str.filterIndexedTo(filterResults) { index, _ -> index == 0 }
// filterResults contains results of both operations
println("Combined Result of both operations $filterResults")
}
Output:
Combined Result of both operations [Computer, Portal, Geeks]As we discussed above we can pass the collection operation result to another function and these functions return the destination collection back, so we can create it right in the corresponding argument of the function call:
Kotlin program of storing result in Hashset:
fun main() {
val str = listOf("Geeks", "for", "Geeks", "A", "Computer", "Portal")
// filter strings right into a new hash set,
// and eliminating duplicates in the result
val result = str.mapTo(HashSet()) { it.length }
// print hashset
println("Only Distinct item length return by hashset $result")
}
Output:
Only Distinct item length return by hashset [1, 3, 5, 6, 8]Write operations (Mutable Collections)
When you're using mutable collections (like MutableList, MutableSet, or MutableMap), you can directly change their contents. Kotlin gives you write operations for that like add(), remove(), clear(), and more. Some functions behave differently depending on whether you want to change the original or create a new result.
For example:
- sort() changes the list in-place (the original list is changed).
- sorted() returns a new sorted list (original list stays the same).
Kotlin program of using sort() and sorted() operation:
fun main() {
val mutableList = mutableListOf(3, 1, 4, 2)
val sortedList = mutableList.sorted()
println("Original still unsorted: $mutableList")
println("New sorted list: $sortedList")
mutableList.sort()
println("Original list after in-place sort: $mutableList")
}
Output:
Original still unsorted: [3, 1, 4, 2]
New sorted list: [1, 2, 3, 4]
Original list after in-place sort: [1, 2, 3, 4]