1. Overview

In this tutorial, we’ll learn to convert a list of objects into a simple list of strings in Kotlin.

Consequently, to understand the requirement, let’s assume we’ve got a list of objects of any type, like a custom data class, any custom class, or any class from the standard library or primitive types. Given that, now we want to convert it to a simple list of strings in Kotlin.

Consequently, we’ll look at the map() transformation function and other ways to achieve this in Kotlin.

2. Problem Statement to Transform a List of Objects to a List of String

Firstly, to understand the transformation, we’ll consider a custom Employee data class, a list of Employee objects, and transform it into a list of employee names. We’ve got the name function in the Employee data class that concatenates first and last names:

data class Employee (
    val empId: Int,
    val firstName: String,
    val lastName: String,
    val monthlySalary: Double) {
    fun name(): String {
        return "$firstName $lastName"
    }
}

Secondly, let’s create a list of Employee:

private val empList = listOf(
    Employee(1,"John", "Doe", Random.nextDouble(1000.0, 5000.0)),
    Employee(2,"Jill", "Fowler", Random.nextDouble(1000.0, 5000.0)),
    Employee(3,"Jack", "Smith", Random.nextDouble(1000.0, 5000.0)),
    Employee(4,"John", "Doe", Random.nextDouble(1000.0, 5000.0)),
)

Finally, let’s create a list of names using the same name from the employee list. We’ll use this list of names to compare against and assert the results of transformation in the subsequent sections:

private val expectedEmpNames = listOf("John Doe", "Jill Fowler", "Jack Smith", "John Doe")

3. Use map() to Transform a List of Objects to a List of String

In this section, we’ll see different variants of map() function usage to transform a list of Employee to a list of employee names.

3.1. Using map() Function

Here, we use the map() function to transform a list of Employee into a list of employee names. The lambda function passed to the map() function calls the name function to return the Employee‘s name. As a result, we get the list of employee names.

val empNameList = empList.map { it.name() }
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmpNames)

3.2. Using mapNotNull()

We can use the mapNotNull() transformation function to filter out the null values from the resultant list. Firstly, we’ll add a null value to our existing list of Employee:

val empListWithNulls = listOf(*empList.toTypedArray(), null)
val empNameList = empListWithNulls.mapNotNull { it?.name() }
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmpNames)

3.3. Using mapTo()

Here, we use the mapTo() function to transform each element of a collection and then append the transformed result to another collection:

val empNameList = mutableListOf<String>()
empList.mapTo(empNameList) { it.name() }
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmpNames)

3.4. Using mapIndexed()

In case we need to access the index of the elements in addition to the item itself in a collection, we can use the mapIndexed() transformation function:

val empNameList = empList.mapIndexed { index, item ->
    item.name()
}
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmployeeNames)

4. Use for Loop to Transform a List of Objects to a List of Strings

We know there are multiple variations of for loops in Kotlin. Some of the for loop variants are index-based, range expression-based, and forEach-based. Consequently, we can use any for loop variant to transform a list of Employee into a list of employee names.

As an example, in the below code snippet, we use iterative for loop to iterate over the employee list, retrieve the name of each employee, and store the name into another list:

val empNameList = mutableListOf<String>()
for (emp in empList) {
    empNameList.add(emp.name())
}
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmployeeNames)

In another example, we use forEach loop-based solution:

val empNameList = mutableListOf<String>()
empList.forEach { emp ->
    empNameList.add(emp.name())
}
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmployeeNames)

5. Using flatMap() to Transform a Nested List of Objects to a List of Strings

In addition to the map() function, Kotlin provides another transformation function, flatMap(), which flattens a collection of collections. For transformation, we can supply a transformation lambda function as the first argument to this function. So, to better understand it, we’ll consider a custom Organization data class in addition to the Employee data class. This Organization class contains an id and a list of Employee objects.

The below code shows the structure of the Organization data class:

data class Organization (
    val orgId: Int,
    val employees: List<Employee>
)

Here is the list of organizations, each containing a list of employees:

val empByOrgList = listOf(
  Organization(
    100,
    listOf(
      Employee(1, "John", "Doe", 1200.0),
      Employee(2, "Jill", "Fowler", 1200.0)
    )
  ),
  Organization(
    200,
    listOf(
      Employee(3, "Jack", "Smith", 1200.0),
      Employee(4, "John", "Doe", 1200.0)
    )
  ),
)

And now, we’ll transform it into a list of all employee names across all organizations:

val empNameList = empByOrgList
  .flatMap { it.employees }
  .map { it.name() }
assertTrue(empNameList.isNotEmpty())
assertTrue(empNameList == expectedEmployeeNames)

6. Conclusion

In this tutorial, we looked at the map() and various transformation functions in Kotlin. Consequently, using this transformation function, we looked at how we could transform a list of custom objects into a simple list of strings.

As always, code snippets can be found over on GitHub.

Comments are closed on this article!