ForEach bersarang di Kotlin

1. Perkenalan

Dalam tutorial Kotlin singkat ini, kita akan melihat cakupan parameter di dalam lambda loop forEach .

Pertama, kami mendefinisikan data yang akan kami gunakan dalam contoh kami. Kedua, kita akan melihat bagaimana menggunakan forEach untuk melakukan iterasi pada daftar. Ketiga, kita akan melihat bagaimana menggunakannya dalam loop bersarang.

2. Uji Data

Data yang akan kami gunakan adalah daftar negara, masing-masing berisi daftar kota, yang pada gilirannya, berisi daftar jalan:

class Country(val name : String, val cities : List) class City(val name : String, val streets : List) 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

Untuk mencetak nama masing-masing negara dalam daftar, kita dapat menulis kode berikut:

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

Sintaks di atas mirip dengan Java. Namun, dalam Kotlin, jika lambda menerima hanya satu parameter, kita dapat menggunakan itu sebagai nama parameter default dan tidak perlu nama itu secara eksplisit:

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

Di atas juga setara dengan:

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

Hal ini bermanfaat untuk catatan bahwa kita hanya dapat menggunakan itu sebagai nama parameter implisit jika tidak ada parameter yang jelas.

Misalnya, berikut ini tidak berfungsi:

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

Dan kita akan melihat kesalahan pada waktu kompilasi:

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

4. Bersarang forEach

Jika kita ingin mengulang di semua negara, kota, dan jalan, kita bisa menulis loop bersarang:

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

Di sini, yang pertama itu mengacu pada sebuah negara, yang kedua itu ke kota dan yang ketiga itu ke jalan.

Namun, jika kami menggunakan IntelliJ, kami melihat peringatan:

Implicit parameter 'it' of enclosing lambda is shadowed

Ini mungkin tidak menjadi masalah, tapi, di baris 6 kita tidak bisa merujuk ke negara atau kota lagi. Jika kita menginginkannya, kita perlu memberi nama parameter secara eksplisit :

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

5. Alternatif untuk Nested Loops

Loop bersarang umumnya sulit dibaca dan harus dihindari jika memungkinkan. Salah satu opsinya adalah menggunakan flatMap () :

fun allStreetsFlatMap() { countries.flatMap { it.cities} .flatMap { it.streets} .forEach { println(it) } }

Namun, jika kita tidak menggunakan flatMap bersarang , kita tidak dapat mengakses nama kota atau jalan di pernyataan println . Jika kita ingin memiliki keluaran yang sama seperti pada metode allTable () di atas dan menghindari bersarang, kita dapat menambahkan dua fungsi ekstensi:

fun City.getStreetsWithCityName() : List { return streets.map { "$name, $it" } .toList() } fun Country.getCitiesWithCountryName() : List { return cities.flatMap { it.getStreetsWithCityName() } .map { "$name, $it" } }

Dan kemudian gunakan dua metode ini dengan satu flatMap :

fun allFlatMapTable() { countries.flatMap { it.getCitiesWithCountryName() } .forEach { println(it) } }

6. Kesimpulan

Dalam artikel singkat ini, kita melihat bagaimana menggunakan default parameter itu di Kotlin dan cara mengakses parameter dari luar forEach dari dalam bersarang forEach lingkaran. Terakhir, kami juga melihat cara menghindari loop bersarang menggunakan fungsi flatMap dan ekstensi.

Semua cuplikan kode dalam artikel ini dapat ditemukan di repositori GitHub kami.