ProgrammationDéveloppeur Android

Décrivez le mécanisme de fonctionnement des collections en Kotlin : différences entre List, MutableList, Set, MutableSet, Map, MutableMap. Quels pièges peuvent surgir lors de leur utilisation ? Donnez des exemples de code.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Kotlin propose deux types de collections : immutable (non modifiables) et mutable (modifiables).

  • List — liste non modifiable. Il est impossible d'ajouter ou de supprimer des éléments.
  • MutableList — liste modifiable : il est possible d'ajouter et de supprimer des éléments.
  • Set — ensemble non modifiable (éléments uniques).
  • MutableSet — ensemble modifiable.
  • Map — tableau associatif (clé-valeur), non modifiable.
  • MutableMap — tableau associatif modifiable.

Exemple de code:

val fruits: List<String> = listOf("Apple", "Banana", "Cherry") val mutableFruits: MutableList<String> = mutableListOf("Apple", "Banana") mutableFruits.add("Cherry") val fruitSet: Set<String> = setOf("Apple", "Banana") // Unicité des éléments val mutableFruitSet: MutableSet<String> = mutableSetOf("Apple", "Banana") mutableFruitSet.add("Cherry") val scores: Map<String, Int> = mapOf("Tom" to 80, "Jane" to 90) val mutableScores: MutableMap<String, Int> = mutableMapOf("Tom" to 80) mutableScores["Jane"] = 90

Subtilités :

  • Les collections sont immuables par défaut.
  • De nombreuses fonctions de retour de listes de la bibliothèque standard retournent List (et non MutableList).
  • Lors de l'utilisation des collections, il est important de ne pas modifier celles qui n'ont pas été conçues pour être modifiées.

Question piège.

Si vous avez une fonction qui prend List<T> comme paramètre, pouvez-vous modifier cette liste à l'intérieur de la fonction ?

Réponse : Non, si le paramètre est de type List<T>, il est impossible d'ajouter ou de supprimer des éléments à l'intérieur de la fonction. Mais si un MutableList<T> est effectivement passé, il peut être converti en ce type (ce qui comporte un risque) :

fun modifyList(list: List<String>) { if (list is MutableList) { list.add("Another") // Fonctionne si la collection d'origine est modifiable } }

Il est déconseillé de procéder ainsi, car cela viole le contrat (List doit être non modifiable !).

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Dans un grand projet, nous avons utilisé une fonction qui prenait List<Customer>, et nous avons essayé d'y ajouter un nouvel élément à l'intérieur de la fonction. L'erreur de compilation (add/clear/remove non définis pour List) n'a été détectée qu'au cours de la révision, car une liste modifiable était nécessaire pour transformer les données.


Histoire

Une collection a été déclarée comme MutableList, mais a été passée à plusieurs threads sans synchronisation. En conséquence, des modifications concurrentes ont entraîné une "ConcurrentModificationException" et une corruption de l'état de la liste. L'erreur a été recherchée longtemps, sans prendre en compte la sécurité des threads.


Histoire

Dans l'un des services de traitement des résultats de requêtes depuis la base de données, nous avons utilisé mutableListOf, puis avons renvoyé la référence à l'extérieur. Le code tiers a, par erreur, vidé la liste. En conséquence, des données vides parvenaient à l'utilisateur, car les références n'étaient pas clonées et les collections modifiables étaient modifiées en dehors de la couche de logique métier.