Sling Academy
Home/Kotlin/Transforming Collections with `map`, `flatMap`, and `mapNotNull` in Kotlin

Transforming Collections with `map`, `flatMap`, and `mapNotNull` in Kotlin

Last updated: December 04, 2024

Working with collections is a common task in programming, and Kotlin provides several powerful functions to transform collections efficiently. Among these, map, flatMap, and mapNotNull are widely used for their versatility and clarity. In this article, we will delve into how these functions work and provide examples to demonstrate their usage effectively.

Understanding map

The map function transforms each element in a collection and returns a list containing the transformed elements. It is analogous to running a loop that applies a specific function to each element.


val numbers = listOf(1, 2, 3, 4, 5)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers) // Output: [1, 4, 9, 16, 25]

In this example, each number in the list is squared, resulting in a new list with those squared numbers.

The Power of flatMap

The flatMap function is used when each transformation also results in a collection. It transforms each element into an iterable object (e.g., another list) and flattens them into one single list of results.


val fruits = listOf("apple,banana", "orange")
val fruitList = fruits.flatMap { it.split(",") }
println(fruitList) // Output: [apple, banana, orange]

In this example, each string in the list is split into a list of fruits, and these lists are flattened into a single list.

Filtering with mapNotNull

Sometimes, you want to transform a collection while discarding null results. This is where mapNotNull comes into play. It applies a given transformation and automatically removes all null elements from the result.


val names = listOf("John", null, "Doe", "Jane", null)
val nonNullNames = names.mapNotNull { it?.toUpperCase() }
println(nonNullNames) // Output: [JOHN, DOE, JANE]

In this snippet, null values are excluded from the final transformed list, resulting only in valid uppercase names without any null entries.

Comparing map, flatMap, and mapNotNull

Understanding when to use each is crucial for writing clean and efficient data transformation code:

  • Use map when you want to apply a transformation to each element individually.
  • Use flatMap when each element should be transformed into a collection and those collections are to be combined into a single one.
  • Use mapNotNull when the transformation can potentially return null, and you want to discard those in the result.

Practical Example

Let's see a practical example. Assume you have a list of sentences and you want to extract unique words from all sentences.


val sentences = listOf("Kotlin is great", "Kotlin is concise", "Kotlin is safe")
val uniqueWords = sentences
    .flatMap { it.split(" ") }
    .map { it.toLowerCase() }
    .distinct()
println(uniqueWords) // Output: [kotlin, is, great, concise, safe]

In this example, each sentence was split into words and then flattened to a single list of words, which were converted to lowercase and filtered for uniqueness.

Conclusion

Kotlin's map, flatMap, and mapNotNull functions provide extensive power for transforming and filtering collections in your applications. By understanding the differences and best usage scenarios for each, you enrich your Kotlin toolset to write cleaner and more expressive code. Try experimenting with these functions to see firsthand their utility and efficiency.

Next Article: Using Sequences for Lazy Evaluation in Kotlin

Previous Article: Sorting Collections in Kotlin: Built-in Methods

Series: Kotlin Collections

Kotlin

You May Also Like

  • How to Use Modulo for Cyclic Arithmetic in Kotlin
  • Kotlin: Infinite Loop Detected in Code
  • Fixing Kotlin Error: Index Out of Bounds in List Access
  • Setting Up JDBC in a Kotlin Application
  • Creating a File Explorer App with Kotlin
  • How to Work with APIs in Kotlin
  • What is the `when` Expression in Kotlin?
  • Writing a Script to Rename Multiple Files Programmatically in Kotlin
  • Using Safe Calls (`?.`) to Avoid NullPointerExceptions in Kotlin
  • Chaining Safe Calls for Complex Operations in Kotlin
  • Using the Elvis Operator for Default Values in Kotlin
  • Combining Safe Calls and the Elvis Operator in Kotlin
  • When to Avoid the Null Assertion Operator (`!!`) in Kotlin
  • How to Check for Null Values with `if` Statements in Kotlin
  • Using `let` with Nullable Variables for Scoped Operations in Kotlin
  • Kotlin: How to Handle Nulls in Function Parameters
  • Returning Nullable Values from Functions in Kotlin
  • Safely Accessing Properties of Nullable Objects in Kotlin
  • How to Use `is` for Nullable Type Checking in Kotlin