Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 4536

Nested forEach in Kotlin

$
0
0

1. Introduction

In this short Kotlin tutorial, we’ll look at the parameter scope inside a forEach loop’s lambda.

First, we define the data which we’ll use in our examples. Second, we’ll see how to use forEach to iterate over a list. Third, we’ll look at how to use it in nested loops.

2. Test Data

The data we’ll use is a list of countries, each containing a list of cities, which in turn, contain a list of streets:

class Country(val name : String, val cities : List<City>)

class City(val name : String, val streets : List<String>)

class World {

    val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht")
    val streetsOfBerlin = listOf("Unter den Linden","Tiergarten")
    val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof")
    val countries = listOf(
      Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht),
        City("Amsterdam", streetsOfAmsterdam))),
      Country("Germany", listOf(City("Berlin", streetsOfBerlin))))
}

3. Simple forEach

To print the name of each country in the list, we can write the following code:

fun allCountriesExplicit() { 
    countries.forEach { c -> println(c.name) } 
}

The above syntax is similar to Java. However, in Kotlin, if the lambda accepts only one parameter, we can use it as the default parameter name and do not need to name it explicitly:

fun allCountriesIt() { 
    countries.forEach { println(it.name) } 
}

The above is also equivalent to:

fun allCountriesItExplicit() {
    countries.forEach { it -> println(it.name) }
}

It’s worthwhile to note that we can only use it as an implicit parameter name if there’s no explicit parameter.

For example, the following doesn’t work:

fun allCountriesExplicit() { 
    countries.forEach { c -> println(it.name) } 
}

And we’ll see an error at compile-time:

Error:(2, 38) Kotlin: Unresolved reference: it

4. Nested forEach

If we want to iterate over all countries, cities, and streets, we can write a nested loop:

fun allNested() {
    countries.forEach {
        println(it.name)
        it.cities.forEach {
            println(" ${it.name}")
            it.streets.forEach { println("  $it") }
        }
    }
}

Here, the first it refers to a country, the second it to a city and the third it to a street.

However, if we use IntelliJ, we see a warning:

Implicit parameter 'it' of enclosing lambda is shadowed

This might not be a problem, but, in line 6 we cannot refer to the country or city anymore. If we want that, we need to explicitly name the parameter:

fun allTable() {
    countries.forEach { c ->
        c.cities.forEach { p ->
            p.streets.forEach { println("${c.name} ${p.name} $it") }
        }
    }
}

5. Conclusion

In this short article, we saw how to use the default parameter it in Kotlin and how to access the parameters of an outer forEach from within a nested forEach loop.

All the code snippets in this article can be found in our GitHub repository.


Viewing all articles
Browse latest Browse all 4536

Trending Articles