Understanding Kotlin Collections: A Step-by-Step Guide for Beginners and Experts

ยท

9 min read

Understanding Kotlin Collections: A Step-by-Step Guide for Beginners and Experts

When programming, it is useful to be able to group data into structures for later processing. Kotlin provides collections for exactly this purpose. One of the key features of Kotlin is its rich set of collection types, which provide developers with a wide range of options for storing and manipulating data. In this blog post, we will explore the various collection types available in Kotlin and discuss their features and use cases.

Introduction to Collections

Collections in Kotlin are used to store and manipulate groups of related objects. Kotlin provides a rich set of collection types that can be broadly categorized into two main categories: read-only collections and mutable collections. Read-only collections are collections that cannot be modified once they are created, while mutable collections are collections that can be modified after they are created.

Kotlin has the following collections for grouping items:

Difference Between Read-Only Collections and Mutable Collections

List

Lists store items in the order that they are added, and allow for duplicate items.

To create a read-only list (List), use the listOf() function.

val list = listOf(1, 2, 3, 4, 5)
println(list[0]) 

// Output: 1

To create a mutable list (MutableList), use the mutableListOf() function.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.add(6)
println(mutableList) 

// Output: [1, 2, 3, 4, 5, 6]

// Mutable list with explicit type declaration
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// Output: [triangle, square, circle]

Functions and Operators that can be used with List.

Lists are ordered so to access an item in a list, use the indexed access operator[]:

val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")

// Output: The first item in the list is: triangle

To get the first or last item in a list, use .first() and .last() functions respectively:

val colors = listOf("red", "green", "blue")
println("The first item in the list is: ${colors.first()}")
println("The Last item in the list is: ${colors.last()}")

// The first item in the list is: red
// The Last item in the list is: blue

To get the number of items in a list, use the .count() function:

val colors = listOf("red", "green", "blue")
println("This list has ${colors.count()} items")

// Output: This list has 3 items

To check that an item is in a list, use the in operator:

val colors = listOf("red", "green", "blue")
println("blue" in colors)

// Output: true

subList Returns a view of the portion of this list between the specified fromIndex (inclusive) and toIndex (exclusive).

val list = listOf(1, 2, 3, 4, 5)
println(list.subList(1, 3)) 

// Output: [2, 3]

sorted Returns a new list containing all elements of the original list sorted according to their natural sort order.

val list = listOf(3, 1, 4, 2, 5)
println(list.sorted()) 

// Output: [1, 2, 3, 4, 5]

size Returns the size of the list.

val list = listOf(1, 2, 3, 4, 5)
println(list.size) 

// Output: 5

contains Checks if the list contains a specific element.

val list = listOf(1, 2, 3, 4, 5)
println(list.contains(3)) 

// Output: true

indexOf Returns the index of the first occurrence of the specified element in the list.

val list = listOf(1, 2, 3, 4, 5)
println(list.indexOf(3)) 

// Output: 2

sorted Returns a new list containing all elements of the original list sorted according to their natural sort order.

val list = listOf(3, 1, 4, 2, 5)
println(list.sorted()) 

// Output: [1, 2, 3, 4, 5]

MutableList Functions

add: Adds the specified element to the end of the list.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.add(6)
println(mutableList) 

// Output: [1, 2, 3, 4, 5, 6]

addAll: Adds all elements from the specified collection to the end of the list.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.addAll(listOf(6, 7, 8))
println(mutableList) 

// Output: [1, 2, 3, 4, 5, 6, 7, 8]

remove: Removes the first occurrence of the specified element from the list.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.remove(3)
println(mutableList) 

// Output: [1, 2, 4, 5]

removeAt: Removes the element at the specified index from the list.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.removeAt(2)
println(mutableList) 

// Output: [1, 2, 4, 5]

clear: Removes all elements from the list.

val mutableList = mutableListOf(1, 2, 3, 4, 5)
mutableList.clear()
println(mutableList) 

// Output: []

Set

Whereas lists are ordered and allow duplicate items, sets are unordered and only store unique items.

To create a read-only set (Set), use the setOf() function.

// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)

// Output: [apple, banana, cherry]

You can see in the previous example that because sets only contain unique elements, the duplicate "cherry" item is dropped.

To create a mutable set (MutableSet), use the mutableSetOf() function.

val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
println(fruit)

// Output: [apple, banana, cherry]

Functions that can be used with Set.

size: Returns the size of the set.

val set = setOf(1, 2, 3, 4, 5)
println(set.size) 

// Output: 5

count(): Returns the size of the set.

val set = setOf(1, 2, 3, 4, 5)
println(set.count() 

// Output: 5

in: To check that an item is in a set

val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)

// Output: true

contains: Checks if the set contains a specific element.

val set = setOf(1, 2, 3, 4, 5)
println(set.contains(3)) 

// Output: true

isEmpty: Checks if the set is empty.

val set = setOf<Int>()
println(set.isEmpty()) 

// Output: true

union: Returns a new set containing all elements from both sets.

val set1 = setOf(1, 2, 3)
val set2 = setOf(3, 4, 5)
println(set1.union(set2)) 

// Output: [1, 2, 3, 4, 5]

intersect: Returns a new set containing only the elements that are present in both sets.

val set1 = setOf(1, 2, 3)
val set2 = setOf(3, 4, 5)
println(set1.intersect(set2))

 // Output: [3]

MutableSet Functions

add: Adds the specified element to the set.

val mutableSet = mutableSetOf(1, 2, 3, 4, 5)
mutableSet.add(6)
println(mutableSet)

 // Output: [1, 2, 3, 4, 5, 6]

addAll: Adds all elements from the specified collection to the set.

val mutableSet = mutableSetOf(1, 2, 3, 4, 5)
mutableSet.addAll(setOf(6, 7, 8))
println(mutableSet) 

// Output: [1, 2, 3, 4, 5, 6, 7, 8]

remove: Removes the specified element from the set.

val mutableSet = mutableSetOf(1, 2, 3, 4, 5)
mutableSet.remove(3)
println(mutableSet) 

// Output: [1, 2, 4, 5]

clear: Removes all elements from the set.

val mutableSet = mutableSetOf(1, 2, 3, 4, 5)
mutableSet.clear()
println(mutableSet) 

// Output: []

Map

  • Maps store items as key-value pairs.

  • You access the value by referencing the key.

  • Every key in a map must be unique so that Kotlin can understand which value you want to get.

  • You can have duplicate values in a map.

  • Maps are useful if you want to look up a value without using a numbered index, like in a list.

To create a read-only map (Map), use the mapOf() function.

The easiest way to create maps is to use to between each key and its related value:

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)

// Output: {apple=100, kiwi=190, orange=100}

When creating maps, Kotlin can infer the type of items stored. To declare the type explicitly, add the types of the keys and values within angled brackets <> after the map declaration. For example: MutableMap<String, Int>. The keys have type String and the values have type Int.

To create a mutable map (MutableMap), use the mutableMapOf() function.

// Mutable map with explicit type declaration
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)

// Output: {apple=100, kiwi=190, orange=100}

Functions that can be used with Map.

To access a value in a map, use the indexed access operator[] with its key:

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")

// Output: The value of apple juice is: 100

size: Returns the number of key-value pairs in the map.

val map = mapOf("a" to 1, "b" to 2, "c" to 3)
println(map.size) 

// Output: 3

.count(): Returns the number of key-value pairs in the map.

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")

// Output: This map has 3 key-value pairs

containsKey: Checks if the map contains a specific key.

val map = mapOf("a" to 1, "b" to 2, "c" to 3)
println(map.containsKey("b"))

 // Output: true

containsValue: Checks if the map contains a specific value.

val map = mapOf("a" to 1, "b" to 2, "c" to 3)
println(map.containsValue(2)) 

// Output: true

To obtain a collection of the keys or values of a map, use the keys and values properties respectively:

keys and values are examples of properties of an object. To access the property of an object, write the property name after the object appended with a period .

val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)

// Output: [apple, kiwi, orange]

println(readOnlyJuiceMenu.values)

// Output: [100, 190, 100]

MutableMap Functions

put: Associates the specified value with the specified key in the map.

val mutableMap = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
mutableMap.put("d", 4)
println(mutableMap) 

// Output: {a=1, b=2, c=3, d=4}

putAll: Copies all of the mappings from the specified map to this map.

val mutableMap = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
mutableMap.putAll(mapOf("d" to 4, "e" to 5))
println(mutableMap) 

// Output: {a=1, b=2, c=3, d=4, e=5}

remove: Removes the mapping for the specified key from the map.

val mutableMap = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
mutableMap.remove("b")
println(mutableMap) 

// Output: {a=1, c=3}

clear: Removes all mappings from the map.

val mutableMap = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
mutableMap.clear()
println(mutableMap) 

// Output: {}

Difference between List, Set and Map

Kotlin collections provide a powerful and flexible way to store and manipulate data. Whether you need a read-only collection or a mutable collection, Kotlin has you covered with its rich set of collection types. By understanding the differences between read-only and mutable collections and exploring the various collection types available in Kotlin, you can make informed decisions about which collection type to use for your specific use case.

ย