Genest voor elk in Kotlin

1. Inleiding

In deze korte Kotlin-tutorial kijken we naar het parameterbereik binnen een voor elk lambda van de lus.

Eerst definiëren we de gegevens die we in onze voorbeelden zullen gebruiken. Ten tweede zullen we zien hoe voor elk om een ​​lijst te herhalen. Ten derde zullen we kijken hoe we het in geneste lussen kunnen gebruiken.

2. Testgegevens

De gegevens die we zullen gebruiken, zijn een lijst met landen, elk met een lijst met steden, die op hun beurt een lijst met straten bevatten:

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 stratenOfMaastricht = listOf (" Grote Gracht "," Vrijthof ") val landen = listOf (Land (" Nederland ", listOf (Stad (" Maastricht ", stratenOfMaastricht), Stad (" Amsterdam ", streetsOfAmsterdam ))), Land ("Duitsland", listOf (Stad ("Berlijn", stratenOfBerlin))))} 

3. Simpel voor elk

Om de naam van elk land in de lijst af te drukken, kunnen we de volgende code schrijven:

fun allCountriesExplicit () {landen.forElke {c -> println (c.name)}} 

De bovenstaande syntaxis is vergelijkbaar met Java. Als de lambda in Kotlin echter maar één parameter accepteert, kunnen we het als de standaard parameternaam en hoef deze niet expliciet te noemen:

fun allCountriesIt () {landen.forElke {println (it.name)}}

Het bovenstaande is ook gelijk aan:

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

Het is de moeite waard om op te merken dat we alleen kunnen gebruiken het als een impliciete parameternaam als er geen expliciete parameter is.

Het volgende werkt bijvoorbeeld niet:

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

En we zullen een fout zien tijdens het compileren:

Fout: (2, 38) Kotlin: onopgeloste referentie: it 

4. Genest voor elk

Als we alle landen, steden en straten willen herhalen, kunnen we een geneste lus schrijven:

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

Hier, de eerste het verwijst naar een land, de tweede het naar een stad en de derde het naar een straat.

Als we echter IntelliJ gebruiken, zien we een waarschuwing:

De impliciete parameter 'it' van het omsluiten van lambda wordt overschaduwd

Dit is misschien geen probleem, maar in regel 6 kunnen we niet meer naar het land of de stad verwijzen. Als we dat willen, moeten we de parameter expliciet een naam geven:

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

5. Alternatieven voor geneste lussen

Geneste lussen zijn over het algemeen moeilijk te lezen en moeten indien mogelijk worden vermeden. Een optie is om te gebruiken flatMap ():

fun allStreetsFlatMap () {landen.flatMap {it.cities} .flatMap {it.streets}. voor elke {println (it)}}

Als we echter geen genest flatMap, hebben we geen toegang tot de stads- of straatnaam in het println uitspraak. Als we dezelfde uitvoer willen hebben als in de bovenstaande methode allTable () en om nesten te vermijden, zouden we twee extensiefuncties kunnen toevoegen:

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

En gebruik vervolgens deze twee methoden met een enkele flatMap:

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

6. Conclusie

In dit korte artikel hebben we gezien hoe we de standaardparameter kunnen gebruiken het in Kotlin en hoe je toegang krijgt tot de parameters van een outer voor elk vanuit een genest voor elk lus. Ten slotte hebben we ook gekeken hoe we geneste lussen kunnen vermijden met flatMap en uitbreidingsfuncties.

Alle codefragmenten in dit artikel zijn te vinden in onze GitHub-repository.


$config[zx-auto] not found$config[zx-overlay] not found