DEV Community

Cover image for Leveraging Kotlin Collections in Android Development
Bugfender
Bugfender

Posted on • Originally published at bugfender.com on

Leveraging Kotlin Collections in Android Development

Kotlin has gradually replaced Java as the lingua franca of Android programming. It’s a more concise language than Java, meaning your code works harder and you can build leaner applications. And Kotlin Collections are fundamental.

These collections play a fundamental role in our work as programmers by simplifying the organization and management of data. Whether it’s a list, set, map or other data structure, they allow us to categorize and store data logically. So we can save, retrieve and manipulate information, and manage a range of tasks from simple data presentation to complex algorithm implementation.

Collections also facilitate code reusability, enabling us to utilize their existing functions and methods rather than developing individual data-handling mechanisms for every task This streamlines development, reduces errors and enhances code maintainability.

If you are new to Android development, you can check our article about the best resources to learn Android development:


The Best Resources to Learn Android Development

At a granular level, collections enable us to perform operations like sorting, filtering, and aggregation efficiently, improving the overall quality of our products.

Overview of Kotlin Collections

Kotlin Collections come in three primary forms: Lists, Maps, and Sets. Each is a distinct type, with its unique characteristics and use cases. Here they are:

Kotlin Lists

  • A Kotlin List is a sequential arrangement of elements that permit duplicate values, preserving the order in which they are added.
  • Elements in a list are accessed by their index, and you can have multiple elements with the same value.
  • Lists are a great help when storing a collection of items whose order needs to be maintained – for example, a to-do list – and storing duplicate values.

Kotlin Maps

  • Kotlin Maps are collections of key-value pairs. In lightweight markdown language, a method allows us to link values with distinct keys, facilitating effortless retrieval of values using their corresponding keys.
  • The keys are also ideal for efficient data retrieval and mapping relationships between entities.
  • Common use cases of Kotlin Maps include building dictionaries, storing settings, and representing relationships between objects.

Kotlin Set

  • A Kotlin Set is an unordered collection of distinct elements, meaning it does not allow duplicate values.
  • Sets are useful when you need to maintain a unique set of elements and do not require a specific order for those elements.
  • Common use cases of Kotlin Sets include tracking unique items, such as unique user IDs, or filtering out duplicates from a list.

The choice between lists, maps, and sets depends on your specific data requirements. Lists are suitable for ordered collections with potential duplicates, maps are ideal for key-value associations, and sets are perfect for maintaining unique, unordered elements.

Kotlin Immutable vs Mutable Collections

Kotlin provides support for both immutable and mutable collections, giving you flexibility when managing data.

Immutable Collections

Immutable collections cannot be modified once they are created. They provide both general safety and specific thread safety, making them ideal for scenarios where you want to keep the data constant. Immutable collections are created using functions like listOf() , mapOf() , and setOf().

Mutable Collections

A mutable collection can be modified after creation. These collections are more flexible and versatile, allowing you to add, remove or modify individual elements. Mutable collections are created using functions like mutableListOf() , mutableMapOf(), and mutableSetOf().

Now that we have a foundational understanding of Kotlin collections, let’s dive deeper into each type.

Using Kotlin List

How to create a list in Kotlin

Creating a Kotlin list is straightforward. Here are two great ways to get started.

Create an immutable list

To create an immutable list we can use listOf(). Check out the following example:

// Example Of listOf function 
fun main(args: Array<String>) {
    //initialize list
    var listA = listOf<String>("Anupam", "Singh", "Developer")

    //accessing elements using square brackets
    println(listA[0])   

    //accessing elements using get()
    println(listA.get(2))   
}
Enter fullscreen mode Exit fullscreen mode

In the Kotlin console, you will see the following output:

[Anupam, native, android, developer]
Enter fullscreen mode Exit fullscreen mode

Create a mutable list

If you want to create a mutable list, we should use the mutableListOf() method. Here is an example:

// Example of mutableListOf function

fun main(args: Array<String>) {
    //initialize a mutable list
    var listA = mutableListOf("Anupam", "Is", "Native")

    //add item to the list
    listA.add("Developer")

    //print the list
    println(listA)
}

Enter fullscreen mode Exit fullscreen mode

And this is the output :

[Anupam, Is, Native, Developer]
Enter fullscreen mode Exit fullscreen mode

Working with a Kotlin List

Now, we’ll look at working with list items.

Accessing elements from the List

We can reach a list item using its place or index. Here’s the first item from the cantChangeList.

// get first item from list 
var cantChangeList = listOf<Int>(1, 2, 3)
val firstItem = cantChangeList[0] 
println(firstItem) //Output: 1
Enter fullscreen mode Exit fullscreen mode

Iterating over a list

There are multiple ways to traverse a list effectively, leveraging higher-order functions such as *forEach* or utilizing for loops. This enables you to handle the list’s elements one after the other, in sequence. For example:

var MyList = listOf<Int>(1, 2, 3)

// print each item from list using for loop 
for (element in myList) {
  println(element)
}

//output:
//1
//2
//3

// print each item from list using forEach loop 
MyList.forEach {
   println(it)
}

// Output:
// 1
// 2
// 3
Enter fullscreen mode Exit fullscreen mode

Adding elements from a list

Modifying a Kotlin List is a great option for mutable lists that harness functions like *add()* , **remove()** , and set(). If we want to add an element to a list, we will simply use the add()method.

// Example of add() function in list

val numberAdd = mutableListOf(1, 2, 3, 4)
numberAdd.add(5)
println(numberAdd) //Output : [1, 2, 3, 4, 5]
Enter fullscreen mode Exit fullscreen mode

Removing elements from a list

Removing elements is also a straightforward process. Here’s a coding example:

// Example of remove() function in list
val numberRemove = mutableListOf(1, 2, 3, 4)
numberRemove.remove(3)      
println(numberRemove) //Output: [1, 2, 4]
Enter fullscreen mode Exit fullscreen mode

Modifying List Items

Altering list items is simple. You can swap them directly with new data via their indices or by using the set commands. Here we have an example of changing an item value, either through its place marker or by using the setmethod:

var myList = mutableListOf<String>("Anupam","five", "test", "change")

// Changing value via index access
myList[0] = "FreshValue"
println(myList[0])

// Ouput:
// FreshValue

// Changing value using set method
myList.set(0, "SetValue")
println(myList[0])

// Ouput:
// SetValue
Enter fullscreen mode Exit fullscreen mode

Other list functions and operations

In Kotlin, list methods are essential tools when we work with collections. While there are numerous methods available, we’ll limit our focus to the most commonly used ones today.

Each of these methods brings its own unique power and utility to a Kotlin collection. Now let’s explore them in detail.

  • sorted() : Returns a new List with elements sorted in natural order.
  • sortedDescending() : Returns a new List with elements sorted in descending order.
  • filter() : Returns a new List containing elements that satisfy a given condition.
  • map() : Transforms each element of the List, based on a given predicate.
  • isEmpty() : Checks whether the List is empty.

Here are some key examples of these methods:

Sort a Kotlin list

This collection includes the following elements (3, 1, 7, 2, 8, 6).

Here they are in ascending order:

// Ascending Sort 
val numbs = mutableListOf(3, 1, 7, 2, 8, 6)
println(numbs)
val sortedNumbs = numbs.sorted()
println(sortedNumbs)

//Output: 

// Before Sort : [3, 1, 7, 2, 8, 6]
// After Sort : [1, 2, 3, 6, 7, 8]

Enter fullscreen mode Exit fullscreen mode

Now, here’s an example of sorting in descending order:

// Descending Sort 

val numbs = mutableListOf(3, 1, 7, 2, 8, 6)
println(numbs)
val sortedDesNumbs = numbs.sortedDescending()
println(sortedDesNumbs)

//Output: 

// Before Sort : [3, 1, 7, 2, 8, 6]
// After Sort : [8, 7, 6, 3, 2, 1]

Enter fullscreen mode Exit fullscreen mode

Filtering a Kotlin list

If you want to filter a Kotlin list, you can use the filter function. This allows you to specify a condition that each element of the list must satisfy in order to be included in the filtered list. Here’s an example:

val listOfData = listOf("Anupam","is","native","android","developer")
val longerThan5 = listOfData.filter { it.length > 5 }
println(longerThan5)

Enter fullscreen mode Exit fullscreen mode

In this example, we have a list of strings under the heading listOfData. We use the filter function to create a new list, longerThan5 , that contains only the strings from listOfData with a length greater than five characters.

Finally, we print the filtered list. The output will be:

[Anupam, native, android, developer]
Enter fullscreen mode Exit fullscreen mode

Check whether a Kotlin list is empty

Here you can use the isEmpty() function, as you can see in this example:

val myList = listOf<Int>()
if (myList.isEmpty()) {
    println("The list is empty.")
} else {
    println("The list is not empty.")
}

// Output:
// The list is empty.

Enter fullscreen mode Exit fullscreen mode

In the following example we’ll create a list, myList , with values using the listOf() function, so the isEmpty will return false:

// example of isEmpty() return false
var list = listOf<String>("Anupam")
if (list.isEmpty()) {
    println("Its empty.")
} else {
    println("Its not empty.")
}

// Output:
// Its not empty.

Enter fullscreen mode Exit fullscreen mode

Transforming a list using map

As we mentioned earlier, the Kotlin map function is a powerful tool for transforming each element of a list into a new form. It applies a specified transformation function to each element and returns a new list with the results. This gives us a concise way to modify the elements in a list, without mutating the original collection.

val numbers = listOf(1, 2, 3, 4, 5)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers) 

// Output: 
// [1, 4, 9, 16, 25]

Enter fullscreen mode Exit fullscreen mode

In this example, we have a list called numbers, containing integers. We apply the map function to numbers and provide a lambda expression as the transformation function. The lambda expression takes each element in the numbers list and returns its square. The map function applies this transformation to each element of the list and creates a new list, squaredNumbers, with the squared values.

Searching elements in a List

Check whether element exists in the list

To search for an element in a Kotlin list, you can utilize the various methods available in the Kotlin standard library. One widely used method is the contains() function, which allows you to check whether a list contains a specific element.

Here’s an example of how you can use the contains() function in Kotlin:

val myList = listOf("apple", "banana", "orange")

val isElementFound = myList.contains("banana")

if (isElementFound) {
   println("Element found!")
} else {
   println("Element not found!")
}

// Output:
// banana

Enter fullscreen mode Exit fullscreen mode

You can also use the filter() method we mentioned earlier to filter all the elements that match a given criteria.

Search the element and get its index

Another option is to use the indexOf() method, which returns the specific position of an element in the list.

val myList = listOf("apple", "banana", "orange")
val index = myList.indexOf("banana")

if (index != -1) {
   println("Element found at index $index")
} else {
   println("Element not found in the list")
}

// Output:
// Element found at index 1

Enter fullscreen mode Exit fullscreen mode

One of the topics that can cause the most headaches for developers is learning how to deal with Dates and Times in any programming language. That’s why we have written an insightful article on how to handle Date and Time in Android development using Kotlin.


Mastering Date and Time Handling in Kotlin for Android Developers

Working with Kotlin Map

Accessing and modifying a Kotlin Map

Creating and initializing a map in Kotlin

In Kotlin, you can create and initialize a map by utilizing either the mapOf() function for immutable maps or the mutableMapOf() function for mutable maps. Here is an example of how you can create a map containing names and ages:

// Immutable Map Example. Syntax is mapOf<key,value>
val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")  
for(key in myImmuMap.keys){  
    println(myImmuMap[key])
}

// Output : 
// Anupam
// Singh
// Developer

Enter fullscreen mode Exit fullscreen mode

The mapOf() function allows you to create an immutable map, ensuring that its content cannot be altered once initialized. Conversely, the **mutableMapOf()** function enables you to modify the map, transforming it into a mutable map.

In the example provided, the map contains pairs of names and ages. Each pair is created using the ‘to’ keyword, where the name is associated with its corresponding age. The map’s content is enclosed in curly brackets which look like {}.

By utilizing these functions, you can easily create and initialize maps in Kotlin according to your specific needs.

Retrieving map values

To access values in a Map, you use the associated key. For example, to get the value of “Anupam” in ‘immutable map’, you can do the:

val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")  
val valueOfAnupam = myImmuMap["Anupam"] // valueOfAnupam will be 1

Enter fullscreen mode Exit fullscreen mode

Modify a map entry

You can also modify the values in a mutable Map, using keys:

val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")
myImmuMap["Anupam"] = 5 // Update Anupam value from 1 to 5

Enter fullscreen mode Exit fullscreen mode

Iterating over map entries via the map keys

You can use a for loop to iterate over a map. In this case we are iterating the map using the keys property, which contains all the keys present in the Map:

val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")
for(key in myImmuMap.keys){  
    println(myImmuMap[key])  
}

// Output:
// Anupam
// Singh
// Developer

Enter fullscreen mode Exit fullscreen mode

Iterating over map values

We can also use a for loop to iterate over a map’s values, ignoring the map keys:

val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")
for(value in myImmuMap.values){  
    println(value)  
}

// Output:
// Anupam
// Singh
// Developer

Enter fullscreen mode Exit fullscreen mode

Other map functions and operations

Kotlin provides several useful functions and operations for working with maps. Some common ones include:

  • _ keys _ : This method retrieves a set, comprising all the keys present in the map.
  • _ values _ : The values function ensures retrieval of a collection, containing all the values stored in the map.
  • containsKey(key) : Determines whether a key exists in the map.
  • containsValue(value) : Checks whether a value exists in the map.

We have seen keys and values in the previous examples. Now let’s see the other methods in action.

Checking the existence of keys or values in the map

As we have mentioned, you can use the containsKey(key) function to check whether a specific key exists in the map, or the containsValue(value) function to determine whether a particular value is present in the map.

val myImmuMap = mapOf<Int,String>(1 to "Anupam", 2 to "Singh", 3 to "Developer")  

// example of ***containsKey(key)*** 
println(myImmuMap.containsKey(2)) // exists so will print true
println(myImmuMap.containsKey(4)) // not exists so will print false

// Output: 
// true
// false

// example of ***containsValue(value)***
println(myImmuMap. ***containsValue*** ("Ajay")) // not exists so print false
println(myImmuMap. ***containsValue*** ("Anupam")) // exists so print true

// Output : 
// false
// true

Enter fullscreen mode Exit fullscreen mode

Working with Kotlin Set

Creating and manipulating sets in Kotlin

Creating a Kotlin Set is similar to other collections. You can use setOf() for an immutable set and mutableSetOf() for a mutable set. Here’s an example:

// Immutable Set
val intImmutableSet = setOf(1, 2, 3)
for(element in intImmutableSet){  
  println(element)
}

// Output: 
// 1
// 2
// 3

// Mutable Set
val intMutableSet = mutableSetOf(14, 24, 35)
for(element in intMutableSet){  
  println(element)
}

// Output: 
// 14
// 24
// 35

Enter fullscreen mode Exit fullscreen mode

Other useful Kotlin s et operations and functions

Sets have unique characteristics that make them useful in certain scenarios. Common set operations include:

  • union() : Returns a new set that is the union of two sets.
  • intersect() : Returns a new set that is the intersection of two sets.
  • add(element) : A new element is added to enhance the set.
  • remove(element) : Removes an element from the set.

In the following example we show how to use the union() function:

// Example of Union function
val firstNum = setOf(1, 2, 3, 4,5)
val secondNum = setOf(3, 4, 5,6,7,8,9)

val finalUnionNums = firstNum.union(secondNum)

println(finalUnionNums)

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

Enter fullscreen mode Exit fullscreen mode

And here we have an example of intersect()

// Example of Intersect function
val fArray = arrayOf(1,2,3,4,5)
val sArray = arrayOf(2,5,6,7)

val iArray = fArray.intersect(sArray.toList()).toIntArray()

println(Arrays.toString(iArray))

// Output:
// [2, 5]

Enter fullscreen mode Exit fullscreen mode

Iterating over Kotlin Set elements

Iterating through a set bears resemblance to iterating through a list. You can use a ‘for’ loop, or other iterable operations, to process each element.

val intImmutableSet = setOf(1, 2, 3)
for(element in intImmutableSet){  
        println(element)  
    }

// Output: 
// 1
// 2
// 3

Enter fullscreen mode Exit fullscreen mode

Use cases and examples of sets in Kotlin

Sets are particularly useful when you need to maintain a collection of unique elements. For example:

  • Keep track of unique user IDs in a chat application.
  • Ensure that a shopping cart contains only distinct items.
  • Manage tags or categories without duplicates in a content management system.

Sets also simplify the process of checking for duplicates and ensuring data integrity.

FAQs

How do I filter strings from a Kotlin list?

To extract only strings, which can contain elements of any type, utilize the filterIsInstance() method. This method should be invoked on the kist, specifying the type T as String within the filterIsInstance() function.

The appropriate syntax for filtering only string elements within a list is:

var myList: List<Any> = listOf(41, false, "Anupam", 0.4 ,"five", 8, 3)
var filteredList = myList.filterIsInstance<String>()
println("Original List : ${myList}")
println("Filtered List : ${filteredList}")

// Output :
// Original List : [41, false, Anupam, 0.4, five, 8, 3]
// Filtered List : [Anupam,five]

Enter fullscreen mode Exit fullscreen mode

Executing filterIsInstance() will yield a list consisting solely of the String elements present within the original list, if any are found.

How do I define a list of lists in Kotlin?

The Kotlin list function listOf() is employed to generate an unchangeable list of elements. This function accepts multiple arguments and promptly furnishes a fresh list incorporating the provided arguments.

val listOfLists = listOf(
        listOf(1, 2, 3),
        listOf("Anupam", "Singh", "Developer")
    )
    print(listOfLists)

Output:
[[1, 2, 3], [Anupam, Singh, Developer]]

Enter fullscreen mode Exit fullscreen mode

How do I filter only integers from a Kotlin list?

To extract only integers, which can contain elements of any type, you should utilize the filterIsInstance() method. This method should be invoked on the list, specifying the type T as Int within the filterIsInstance() function.

The appropriate syntax for filtering solely integer elements within a list is:

var myList: List<Any> = listOf(5, false, "Anupam", 0.4 ,"five", 8, 3)
var filteredList = myList.filterIsInstance<Int>()
println("Original List : ${myList}")
println("Filtered List : ${filteredList}")

// Output :
// Original List : [5, false, Anupam, 0.4, five, 8, 3]
// Filtered List : [5, 8, 3]

Enter fullscreen mode Exit fullscreen mode

Executing filterIsInstance() will yield a list consisting solely of the Int elements present within the original list, if any are found.

What are the different types of Kotlin Collections?

Kotlin’s official docs provide an overview of collection types in the Kotlin Standard Library, including sets, lists, and maps. For each collection type, there are two interfaces available: a read-only interface that allows accessing collection elements and provides some operations and then a mutable interface collections where you can modify the items. The most common collections are:

  • List
  • Set
  • Map (or dictionary)

How do I find out the length a Kotlin list?

To find out the length of a Kotlin list, you can use the size property. Here is an example:

val myList = listOf(1, 2, 3, 4, 5)
val length = myList.size
println("The length of the list is $length")

Enter fullscreen mode Exit fullscreen mode

Output:

The length of the list is 5

Enter fullscreen mode Exit fullscreen mode

What is List<*> in Kotlin?

In Kotlin, you can create a generic list with an unspecified type. When you use a generic list, you’re essentially saying, “I want a list of something, but I don’t care what type of things are in it”. This can be useful when you are writing generic code that can work with any type of list.

fun printList(list: List<*>) {
    for (item in list) {
        println(item)
    }
}
val intList = listOf(1, 2, 3)
val stringList = listOf("a", "b", "c")

printList(intList) // This will print 1, 2, 3
printList(stringList) // This will print a, b, c

Enter fullscreen mode Exit fullscreen mode

Can we use iterators to iterate a Koltin collection?

Yes, you can use iterators in Kotlin. In the previous examples we have seen how to iterate a Kotlin collection using for or forEach. In case you want to use iterators, here you can see an example of iterating a Kotlin list with an iterator.

val myList = listOf("apple", "banana", "orange")
val iterator = myList.iterator()

while (iterator.hasNext()) {
    val value = iterator.next()
    println(value)
}

Enter fullscreen mode Exit fullscreen mode

In the example, we call iterator() on the list to get the iterator for the list. The while loop then uses hasNext() to check if there is another item in the list and next() to get the value of the current item.

To sum up…

In the realm of Android development, Kotlin Collections provide invaluable tools for managing and manipulating data. Lists, maps, and sets provide different ways to structure and organize information, each with its own set of advantages and use cases.

As you venture further into Android development with Kotlin, a solid understanding of its collections will become a fundamental tool in your kit. If you are developing a complex application, a game, or a basic utility, Kotlin Collections will play a central role in managing many of your data tasks.

In conclusion, you should embrace the power of Kotlin collections , experiment with their capabilities, and integrate them into your projects to enhance your Android development skills. By leveraging lists, maps, and sets effectively, you’ll be better equipped to tackle the challenges of Android app development and build robust, efficient, and user-friendly applications.

If you want to explore other areas about Kotlin development, you can checkout the following article:

Top comments (0)