Collections en Kotlin

1. Avant de commencer

Dans cet atelier de programmation, vous en apprendrez plus sur les collections, ainsi que sur les lambdas et les fonctions d'ordre supérieur en Kotlin.

Conditions préalables

  • Connaissances de base des concepts Kotlin présentés dans les précédents ateliers de programmation.
  • Vous maîtrisez Kotlin Playground pour créer et modifier des programmes Kotlin.

Points abordés

  • Comment utiliser des collections, y compris des ensembles et des maps
  • Les principes de base des lambdas
  • Les principes de base des fonctions d'ordre supérieur

Ce dont vous avez besoin

2. En savoir plus sur les collections

Une collection est un groupe d'éléments connexes, comme une liste de mots ou un ensemble de dossiers d'employés. La collection peut être ordonnée ou non, et les articles peuvent être uniques ou non. Vous connaissez déjà un type de collection : Les listes. Les listes sont ordonnées, mais les éléments n'ont pas à être uniques.

Comme pour les listes, Kotlin fait la distinction entre les collections modifiables et immuables. Kotlin fournit de nombreuses fonctions permettant d'ajouter ou de supprimer des éléments, ainsi que d'afficher et de manipuler des collections.

Créer une liste

Dans cette tâche, vous vous entraînerez à nouveau à créer une liste de chiffres et à la trier.

  1. Ouvrez Kotlin Playground.
  2. Remplacez le code par le code suivant :
fun main() {
    val numbers = listOf(0, 3, 8, 4, 0, 5, 5, 8, 9, 2)
    println("list:   ${numbers}")
}
  1. Exécutez le programme en appuyant sur la flèche verte et observez les résultats :
list:   [0, 3, 8, 4, 0, 5, 5, 8, 9, 2]
  1. La liste contient 10 chiffres compris entre 0 et 9. Certains chiffres apparaissent plusieurs fois, d'autres n'apparaissent pas du tout.
  2. L'ordre des éléments de la liste est important : le premier élément est 0, le deuxième élément est 3, et ainsi de suite. Les éléments resteront dans cet ordre, sauf si vous les modifiez.
  3. Comme nous l'avons vu précédemment, les listes comportent de nombreuses fonctions intégrées, telles que sorted(), qui renvoie une copie de la liste triée par ordre croissant. Après println(), ajoutez une ligne à votre programme pour afficher une copie triée de la liste :
println("sorted: ${numbers.sorted()}")
  1. Exécutez à nouveau votre programme et examinez les résultats :
list:   [0, 3, 8, 4, 0, 5, 5, 8, 9, 2]
sorted: [0, 0, 2, 3, 4, 5, 5, 8, 8, 9]

Une fois les nombres triés, il est plus facile de voir combien de fois ils apparaissent dans votre liste, ou s'ils n'apparaissent pas du tout.

En savoir plus sur les ensembles

Un autre type de collection en Kotlin est un ensemble. Il s'agit d'un groupe d'éléments associés, mais contrairement à une liste, il ne peut pas y avoir de doublons et l'ordre n'a pas d'importance. Un élément peut se trouver dans l'ensemble ou non. S'il fait partie de l'ensemble, il n'existe qu'une seule copie de cet élément. Ce concept est semblable au concept mathématique d'un ensemble. Par exemple, vous avez lu un ensemble de livres. Lire un livre plusieurs fois n'a aucune incidence sur le fait qu'il figure dans l'ensemble de livres que vous avez lus.

  1. Ajoutez ces lignes à votre programme pour convertir la liste en un ensemble :
val setOfNumbers = numbers.toSet()
println("set:    ${setOfNumbers}")
  1. Exécutez votre programme et observez les résultats :
list:   [0, 3, 8, 4, 0, 5, 5, 8, 9, 2]
sorted: [0, 0, 2, 3, 4, 5, 5, 8, 8, 9]
set:    [0, 3, 8, 4, 5, 9, 2]

Le résultat contient tous les numéros de la liste d'origine, mais ils n'apparaissent qu'une seule fois. Notez qu'ils sont dans le même ordre que dans la liste d'origine, mais que cet ordre n'est pas significatif pour un ensemble.

  1. Définissez un ensemble modifiable et un ensemble immuable, puis initialisez-les avec le même ensemble de nombres, mais dans un ordre différent, en ajoutant les lignes suivantes :
val set1 = setOf(1,2,3)
val set2 = mutableSetOf(3,2,1)
  1. Ajoutez une ligne pour indiquer s'ils sont égaux :
println("$set1 == $set2: ${set1 == set2}")
  1. Exécutez votre programme et observez les nouveaux résultats :
[1, 2, 3] == [3, 2, 1]: true

Même si l'un est modifiable et pas l'autre, et que ces ensembles présentent les éléments dans un ordre différent, ils sont considérés comme égaux, car ils contiennent exactement le même ensemble d'éléments.

L'une des principales opérations que vous pouvez effectuer sur un ensemble consiste à vérifier, à l'aide de la fonction contains(), si un élément particulier se trouve ou non dans l'ensemble. Vous avez déjà vu "contains()", mais vous l'avez utilisée sur une liste.

  1. Ajoutez la ligne suivante à votre programme pour afficher si 7 se trouve dans l'ensemble :
println("contains 7: ${setOfNumbers.contains(7)}")
  1. Exécutez votre programme et observez ces nouveaux résultats :
contains 7: false

Vous pouvez également faire le test avec une valeur présente dans l'ensemble.

Tout le code ci-dessus :

fun main() {
    val numbers = listOf(0, 3, 8, 4, 0, 5, 5, 8, 9, 2)
    println("list:   ${numbers}")
    println("sorted: ${numbers.sorted()}")
    val setOfNumbers = numbers.toSet()
    println("set:    ${setOfNumbers}")
    val set1 = setOf(1,2,3)
    val set2 = mutableSetOf(3,2,1)
    println("$set1 == $set2: ${set1 == set2}")
    println("contains 7: ${setOfNumbers.contains(7)}")
}

Comme pour les ensembles mathématiques, en Kotlin, vous pouvez également effectuer des opérations comme l'intersection (∩) ou l'union (∪) de deux ensembles, en utilisant intersect() ou union().

En savoir plus sur les maps

Le dernier type de collection que vous allez découvrir dans cet atelier est la map ou le dictionnaire. Une map est un ensemble de paires clé-valeur conçues pour faciliter la recherche d'une valeur pour une clé spécifique. Les clés sont uniques et correspondent chacune à une seule valeur, mais les valeurs peuvent avoir des doublons. Les valeurs d'une map peuvent être des chaînes, des nombres ou des objets, voire une autre collection telle qu'une liste ou un ensemble.

b55b9042a75c56c0.png

Une map est utile lorsque vous disposez de paires de données et que vous pouvez identifier chaque paire en fonction de sa clé. La clé "correspond à" la valeur correspondante.

  1. Dans Kotlin Playground, remplacez l'intégralité du code par celui-ci afin de créer une map modifiable pour stocker le nom des utilisateurs et leur âge :
fun main() {
    val peopleAges = mutableMapOf<String, Int>(
        "Fred" to 30,
        "Ann" to 23
    )
    println(peopleAges)
}

Cette opération crée une map modifiable d'une String (clé) vers une Int (valeur), initialise la map avec deux entrées et affiche les éléments.

  1. Exécutez votre programme et observez les résultats :
{Fred=30, Ann=23}
  1. Pour ajouter d'autres entrées à la map, vous pouvez utiliser la fonction put(), en transmettant la clé et la valeur :
peopleAges.put("Barbara", 42)
  1. Vous pouvez également utiliser une notation abrégée pour ajouter des entrées :
peopleAges["Joe"] = 51

Voici tout le code ci-dessus :

fun main() {
    val peopleAges = mutableMapOf<String, Int>(
        "Fred" to 30,
        "Ann" to 23
    )
    peopleAges.put("Barbara", 42)
    peopleAges["Joe"] = 51
    println(peopleAges)
}
  1. Exécutez votre programme et observez les résultats :
{Fred=30, Ann=23, Barbara=42, Joe=51}

Comme indiqué ci-dessus, les clés (noms) sont uniques, mais les valeurs (âges) peuvent avoir des doublons. Selon vous, que se passe-t-il si vous essayez d'ajouter un élément en utilisant une même clé ?

  1. Avant println(), ajoutez la ligne de code suivante :
peopleAges["Fred"] = 31
  1. Exécutez votre programme et observez les résultats :
{Fred=31, Ann=23, Barbara=42, Joe=51}

La clé "Fred" n'est pas ajoutée à nouveau, mais la valeur à laquelle elle correspond est définie sur 31.

Comme vous pouvez le voir, les maps sont un moyen rapide de mapper des clés aux valeurs de votre code.

3. Utiliser des collections

Bien qu'ils aient des qualités différentes, des types de collections différents peuvent avoir un comportement identique. Si les collections sont modifiables, vous pouvez ajouter ou supprimer des éléments. Vous pouvez énumérer tous les éléments, rechercher un élément particulier ou parfois convertir un type de collection en un autre. Vous l'avez déjà fait lorsque vous avez converti une List en un Set avec toSet(). Voici quelques fonctions utiles pour travailler avec des collections.

forEach

Supposons que vous souhaitiez afficher les éléments de peopleAges, et inclure le nom et l'âge de la personne. Par exemple, "Fred is 31, Ann is 23,..." (Fred a 31 ans, Anne a 23 ans…), et ainsi de suite. Vous avez découvert les boucles for dans un atelier de programmation précédent. Vous pourriez donc saisir une boucle avec for (people in peopleAges) { ... }.

Cependant, il est courant d'énumérer tous les objets d'une collection. C'est pourquoi Kotlin propose forEach(), qui passe en revue tous les éléments et effectue une opération sur chacun d'entre eux.

  1. Dans Playground, ajoutez le code suivant après println() :
peopleAges.forEach { print("${it.key} is ${it.value}, ") }

Cette méthode ressemble à la boucle for, mais elle est un peu plus compacte. Au lieu de spécifier une variable pour l'élément actuel, forEach utilise l'identifiant spécial it.

Notez que vous n'avez pas besoin d'ajouter de parenthèses lorsque vous avez appelé la méthode forEach(). Il vous suffit de saisir le code entre accolades {}.

  1. Exécutez votre programme et observez ces nouveaux résultats :
Fred is 31, Ann is 23, Barbara is 42, Joe is 51,

Cette valeur est très proche de celle souhaitée, mais il y a une virgule supplémentaire à la fin.

Convertir une collection en une chaîne est une opération récurrente, et ce séparateur supplémentaire à la fin est également un problème tout aussi récurrent. Vous apprendrez à résoudre ce problème dans les prochaines étapes.

map

La fonction map() (à ne pas confondre avec une collection de map ou de dictionnaire ci-dessus) applique une transformation à chaque élément d'une collection.

  1. Dans votre programme, remplacez l'instruction forEach par cette ligne :
println(peopleAges.map { "${it.key} is ${it.value}" }.joinToString(", ") )
  1. Exécutez votre programme et observez ces nouveaux résultats :
Fred is 31, Ann is 23, Barbara is 42, Joe is 51

Le résultat est correct, et aucune virgule n'a été ajoutée. Il se passe beaucoup de choses sur cette ligne, alors regardez attentivement.

  • peopleAges.map applique une transformation à chaque élément de peopleAges et crée une nouvelle collection avec ces éléments transformés.
  • La partie entre accolades {} définit la transformation à appliquer à chaque élément. La transformation prend une paire clé-valeur et la transforme en chaîne. Par exemple <Fred, 31> devient Fred is 31.
  • joinToString(", ") ajoute chaque élément de la collection transformée à une chaîne, séparée par ,, et sait comment ne pas l'ajouter au dernier élément.
  • Tout cela prend la forme d'une chaîne grâce à . (opérateur point). Vous avez déjà vu ceci dans les appels de fonction et accès aux propriétés lors des ateliers de programmation précédents.

filtre

Les collections permettent également de rechercher les éléments qui correspondent à une condition particulière. La fonction filter() renvoie les éléments d'une collection correspondant à une certaine expression.

  1. Après println(), ajoutez les lignes suivantes :
val filteredNames = peopleAges.filter { it.key.length < 4 }
println(filteredNames)

Notez que l'appel de la fonction filter ne nécessite pas de parenthèses, et que it fait référence à l'élément actuel de la liste.

  1. Exécutez votre programme et observez ces nouveaux résultats :
{Ann=23, Joe=51}

Dans ce cas, l'expression obtient la longueur de la clé (une String) et vérifie si elle est inférieure à 4. Tous les éléments qui correspondent, c'est-à-dire tous les noms de moins de 4 caractères, sont ajoutés à la nouvelle collection.

Le type renvoyé lorsque vous avez appliqué le filtre à une map est une nouvelle map (LinkedHashMap). Vous pouvez effectuer un traitement supplémentaire sur la map ou la convertir en un autre type de collection, comme une liste par exemple.

4. En savoir plus sur les lambdas et les fonctions d'ordre supérieur

Lambdas

Reprenons l'exemple précédent :

peopleAges.forEach { print("${it.key} is ${it.value}") }

Une variable (peopleAges) appelle une fonction (forEach). À la place des parenthèses qui suivent le nom de la fonction avec les paramètres, vous voyez du code entre accolades {}. Le même schéma apparaît dans le code qui utilise les fonctions map et filter de l'étape précédente. La fonction forEach est appelée sur la variable peopleAges et utilise le code entre accolades.

C'est comme si vous aviez écrit une petite fonction entre accolades, mais qu'il n'y avait pas de nom. Cette idée, c'est-à-dire une fonction sans nom qui peut être immédiatement utilisée comme expression, est un concept très utile. On parle alors d'expression lambda, ou simplement de lambda.

Cela nous amène à nous questionner sur la manière d'interagir efficacement avec des fonctions en langage Kotlin. Vous pouvez stocker des fonctions dans des variables et des classes, transmettre des fonctions en tant qu'arguments et même renvoyer des fonctions. Vous pouvez les traiter comme des variables d'autres types, comme Int ou String.

Types de fonctions

Pour activer ce type de comportement, Kotlin utilise des types de fonctions, qui vous permettent de définir un type de fonction spécifique selon ses paramètres d'entrée et sa valeur renvoyée. Il se présente au format suivant :

Exemple de type de fonction : (Int) -> Int

Une fonction ayant le type de fonction ci-dessus doit utiliser un paramètre de type Int et renvoyer une valeur de type Int. Dans la notation du type de fonction, les paramètres sont indiqués entre parenthèses (séparés par une virgule s'il y a plusieurs paramètres), suivis d'une flèche ->, puis du type de retour.

Quel type de fonction répond à ce critère ? Vous pouvez avoir une expression lambda qui triple la valeur d'une entrée d'un entier, comme illustré ci-dessous. Pour la syntaxe d'une expression lambda, les paramètres sont placés en premier (surlignés en rouge), suivis de la flèche de fonction, puis du corps de la fonction (surligné en violet). La dernière expression du lambda est la valeur renvoyée.

252712172e539fe2.png

Vous pouvez même stocker un lambda dans une variable, comme dans le schéma ci-dessous. La syntaxe est semblable à celle utilisée pour déclarer une variable d'un type de données de base, par exemple Int. Observez le nom de la variable (surligné en jaune), le type de variable (surligné en bleu) et la valeur de la variable (surlignée en vert). La variable triple stocke une fonction. Son type est un type de fonction (Int) -> Int, et la valeur est une expression lambda { a: Int -> a * 3}.

  1. Essayez ce code dans Playground. Définissez et appelez la fonction triple en lui transmettant un nombre comme 5. 4d3f2be4f253af50.png
fun main() {
    val triple: (Int) -> Int = { a: Int -> a * 3 }
    println(triple(5))
}
  1. Vous devriez obtenir le résultat suivant :
15
  1. Dans les accolades, vous pouvez explicitement omettre le paramètre (a: Int) ainsi que la flèche de fonction (->) et n'avoir que le corps de la fonction. Mettez à jour la fonction triple déclarée dans votre fonction main et exécutez le code.
val triple: (Int) -> Int = { it * 3 }
  1. Le résultat devrait être identique, mais votre lambda est désormais écrit de manière plus concise. Pour plus d'exemples sur les lambdas, consultez cette ressource.
15

Fonctions d'ordre supérieur

Maintenant que vous savez comment manipuler des fonctions en Kotlin, abordons à présent le sujet des fonctions d'ordre supérieur. Il s'agit simplement de transmettre une fonction (dans ce cas, un lambda) à une autre fonction ou d'utiliser une fonction pour renvoyer à une autre.

Il s'avère que les fonctions map, filter et forEach sont des exemples de fonctions d'ordre supérieur, car elles ont toutes une fonction comme paramètre. (Dans le lambda transmis à cette fonction filter, d'ordre supérieur, vous pouvez omettre le paramètre unique ainsi que la flèche, et utiliser le paramètre it.)

peopleAges.filter { it.key.length < 4 }

Voici un exemple d'une nouvelle fonction d'ordre supérieur : sortedWith().

Si vous souhaitez trier une liste de chaînes, vous pouvez utiliser la méthode intégrée sorted() pour les collections. Toutefois, si vous souhaitez trier la liste en fonction de la longueur des chaînes, vous devez écrire du code pour obtenir la longueur de deux chaînes et les comparer. Kotlin vous permet de le faire en transmettant un lambda à la méthode sortedWith().

  1. Dans Playground, créez une liste de noms et triez-la par nom, avec le code suivant :
fun main() {
    val peopleNames = listOf("Fred", "Ann", "Barbara", "Joe")
    println(peopleNames.sorted())
}
  1. Imprimez maintenant la liste triée selon la longueur des noms en transmettant un lambda à la fonction sortedWith(). Le lambda devrait utiliser deux paramètres du même type et renvoyer un Int. Ajoutez cette ligne de code après l'instruction println() dans la fonction main().
println(peopleNames.sortedWith { str1: String, str2: String -> str1.length - str2.length })
  1. Exécutez votre programme et observez les résultats.
[Ann, Barbara, Fred, Joe]
[Ann, Joe, Fred, Barbara]

Le lambda transmis à sortedWith() comporte deux paramètres : str1, qui est un String et str2 qui est un String. Vous voyez alors la flèche de fonction, suivie du corps de la fonction.

7005f5b6bc466894.png

N'oubliez pas que la dernière expression dans le lambda est la valeur renvoyée. Dans ce cas, le lambda renvoie la différence entre la longueur de la première et de la deuxième chaîne, qui est un Int. Cela correspond à ce qui est nécessaire pour le tri : Si str1 est inférieur à str2, il renvoie une valeur inférieure à 0. Si les valeurs str1 et str2 sont de même longueur, la valeur renvoyée est 0. Si str1 est supérieur à str2, il renvoie une valeur supérieure à 0. En effectuant une série de comparaisons entre deux Strings à la fois, la fonction sortedWith() génère une liste avec des noms triés en fonction de leur longueur et par ordre croissant.

OnClickListener et OnKeyListener sur Android

Souvenez-vous des connaissances Android acquises jusqu'à présent. Au cours d'ateliers de programmation précédents, vous avez utilisé des lambdas, par exemple lorsque vous avez configuré un écouteur de clics pour le bouton dans l'application de calcul de pourboire :

calculateButton.setOnClickListener{ calculateTip() }

Utiliser un lambda pour définir l'écouteur de clics est une méthode rapide et pratique. La forme longue de ce code, comparée à la version abrégée, est présentée ci-dessous. Vous n'avez pas besoin de comprendre tous les détails de la version longue, mais vous remarquerez des différences entre les deux versions.

29760e0a3cac26a2.png

Notez que le lambda a le même type de fonction que la méthode onClick() dans OnClickListener (prend un argument View et renvoie Unit, ce qui signifie qu'il n'y a aucune valeur renvoyée).

La version abrégée du code est possible grâce à la conversion SAM (Single-abstraction-Method, ou méthode abstraite unique en français) en Kotlin. Kotlin convertit le lambda en un objet OnClickListener qui implémente la méthode abstraite unique onClick(). Il vous suffit de vérifier que le type de fonction lambda correspond à celui de la fonction abstraite.

Étant donné que le paramètre view n'est jamais utilisé dans le lambda, il peut être omis. Ensuite, nous avons le corps de la fonction dans le lambda.

calculateButton.setOnClickListener { calculateTip() }

Ces concepts étant complexes, vous devez faire preuve de patience, car leur mise en pratique demande du temps et de l'expérience. Prenons un autre exemple. Rappelez-vous que lorsque vous définissez un écouteur de touche dans le champ de texte "Coût de service" de la calculatrice de pourboire, le clavier à l'écran peut alors être masqué lorsque l'utilisateur appuie sur la touche Entrée.

costOfServiceEditText.setOnKeyListener { view, keyCode, event -> handleKeyEvent(view, keyCode) }

Lorsque vous recherchez OnKeyListener, la méthode abstraite comporte les paramètres onKey(View v, int keyCode, KeyEvent event) suivants et renvoie un Boolean. Grâce aux conversions SAM en Kotlin, vous pouvez transmettre un lambda à setOnKeyListener(). Assurez-vous simplement que le lambda a le type de fonction (View, Int, KeyEvent) -> Boolean.

Voici un diagramme de l'expression lambda utilisée ci-dessus. Les paramètres sont "view", "keyCode" et "event". Le corps de la fonction est constitué de handleKeyEvent(view, keyCode), qui utilise les paramètres transmis et renvoie un Boolean.

f73fe767b8950123.png

5. Créer des listes de mots

Appliquons maintenant tout ce que vous avez appris sur les collections, les lambdas et les fonctions d'ordre supérieur à un cas d'utilisation réaliste.

Imaginons que vous souhaitiez créer une application Android pour jouer à un jeu de mots ou pour apprendre des mots de vocabulaire. L'application peut se présenter comme suit, avec un bouton pour chaque lettre de l'alphabet :

7539df92789fad47.png

Cliquez sur la lettre A pour afficher une petite liste de mots commençant par la lettre A, et ainsi de suite.

Vous aurez besoin d'une collection de mots, mais quel genre de collection ? Si l'application doit inclure des mots qui commencent par chaque lettre de l'alphabet, vous devrez chercher ou organiser tous les mots commençant par une lettre donnée. Pour corser les choses, vous choisirez des mots différents dans votre collection chaque fois que l'utilisateur lancera l'application.

Commencez par une liste de mots. Pour une vraie application, vous aurez besoin d'une liste de mots plus longue et de mots commençant par toutes les lettres de l'alphabet, mais une courte liste fera l'affaire pour cet exercice.

  1. Remplacez le code dans Kotlin Playground par le code suivant :
fun main() {
    val words = listOf("about", "acute", "awesome", "balloon", "best", "brief", "class", "coffee", "creative")
}
  1. Pour obtenir une collection de mots commençant par la lettre B, vous pouvez utiliser filter avec une expression lambda. Ajoutez les lignes suivantes :
val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
println(filteredWords)

La fonction startsWith() renvoie la valeur "true" si une chaîne commence par la chaîne spécifiée. Vous pouvez également lui dire d'ignorer la casse pour que "b" corresponde à "b" ou "B".

  1. Exécutez votre programme et observez le résultat :
[balloon, best, brief]
  1. N'oubliez pas que vous souhaitez que les mots apparaissent de manière aléatoire dans votre application. Avec les collections Kotlin, vous pouvez utiliser la fonction shuffled() pour créer une copie d'une collection avec les éléments mélangés aléatoirement. Affichez aussi les mots filtrés de manière aléatoire :
val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
    .shuffled()
  1. Exécutez votre programme et observez les nouveaux résultats :
[brief, balloon, best]

Étant donné que les mots sont mélangés au hasard, ils peuvent s'afficher dans un ordre différent.

  1. Vous ne voulez pas afficher tous les mots (surtout si votre liste est longue), mais seulement quelques-uns. Vous pouvez utiliser la fonction take() pour obtenir les premiers éléments de la collection. Faites en sorte que les mots filtrés n'incluent que les deux premiers mots aléatoires :
val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
    .shuffled()
    .take(2)
  1. Exécutez votre programme et observez les nouveaux résultats :
[brief, balloon]

Là encore, en raison du mélange aléatoire, vous verrez peut-être des mots différents à chaque exécution.

  1. Enfin, vous souhaitez que la liste aléatoire des mots pour chaque lettre soit triée. Comme précédemment, vous pouvez utiliser la fonction sorted() pour renvoyer une copie de la collection avec les éléments triés :
val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
    .shuffled()
    .take(2)
    .sorted()
  1. Exécutez votre programme et observez les nouveaux résultats :
[balloon, brief]

Le code du dessus en entier :

fun main() {
    val words = listOf("about", "acute", "awesome", "balloon", "best", "brief", "class", "coffee", "creative")
    val filteredWords = words.filter { it.startsWith("b", ignoreCase = true) }
        .shuffled()
        .take(2)
        .sorted()
    println(filteredWords)
}
  1. Essayez de modifier le code pour créer une liste d'un mot aléatoire commençant par la lettre "c". Que devez-vous modifier dans le code ci-dessus ?
val filteredWords = words.filter { it.startsWith("c", ignoreCase = true) }
    .shuffled()
    .take(1)

Dans l'application, vous devrez appliquer le filtre pour chaque lettre de l'alphabet, mais vous savez désormais comment générer la liste de mots pour chaque lettre !

Les collections sont puissantes et flexibles. Elles offrent beaucoup de possibilités et plusieurs façons de faire coexistent. À mesure que vous en apprendrez plus sur la programmation, vous saurez définir quel type de collection est adapté au problème que vous rencontrez et quelles sont les meilleures façons de le résoudre.

Les lambdas et les fonctions d'ordre supérieur permettent de travailler avec des collections plus facilement et de façon plus concise. Ces idées étant très utiles, vous les verrez souvent utilisées.

6. Résumé

  • Une collection est un groupe d'éléments associés
  • Les collections peuvent être modifiables ou immuables
  • Les collections peuvent être triées ou non triées
  • Les collections peuvent nécessiter des éléments uniques ou inclure des doublons
  • Kotlin accepte différents types de collections, y compris les listes, les ensembles et les maps
  • Kotlin fournit de nombreuses fonctions pour le traitement et la transformation des collections, y compris forEach, map, filter, sorted, etc.
  • Un lambda est une fonction sans nom pouvant être transmise immédiatement en tant qu'expression. Voici un exemple : { a: Int -> a * 3 }.
  • Une fonction d'ordre supérieur permet de transmettre une fonction à une autre ou de renvoyer une fonction depuis une autre fonction.

7. En savoir plus