Vue d'ensemble de l'API Kotlin Collections

1. Vue d'ensemble

Dans ce rapide didacticiel, nous présenterons l'API Collections de Kotlin, et nous discuterons des différents types de collections dans Kotlin et de certaines opérations courantes sur les collections.

2. Collection vs collection Mutable

Tout d'abord, examinons différents types de collections à Kotlin. Nous verrons comment initialiser les types de collections de base.

L' interface Collection prend en charge les méthodes en lecture seule tandis que MutableCollection prend en charge les méthodes en lecture / écriture.

2.1. liste

Nous pouvons créer un simple en lecture seule liste en utilisant la méthode ListOf () et lecture-écriture MutableList utilisant mutableListOf () :

val theList = listOf("one", "two", "three") val theMutableList = mutableListOf("one", "two", "three")

2.2. Ensemble

De même, nous pouvons créer un Set en lecture seule en utilisant la méthode setOf () et en lecture-écriture MutableSet en utilisant mutableSetOf () :

val theSet = setOf("one", "two", "three") val theMutableSet = mutableSetOf("one", "two", "three")

2.3. Carte

Nous pouvons également créer une carte en lecture seule en utilisant la méthode mapOf () et MutableMap en lecture-écriture en utilisant mutableMapOf () :

val theMap = mapOf(1 to "one", 2 to "two", 3 to "three") val theMutableMap = mutableMapOf(1 to "one", 2 to "two", 3 to "three")

3. Opérateurs utiles

L'API Collections de Kotlin est beaucoup plus riche que celle que nous pouvons trouver en Java - elle est livrée avec un ensemble d'opérateurs surchargés.

3.1. L' opérateur « in»

Nous pouvons utiliser l'expression « x in collection » qui peut être traduite en collection.contains (x) :

@Test fun whenSearchForExistingItem_thenFound () { val theList = listOf("one", "two", "three") assertTrue("two" in theList) }

3.2. L' opérateur «+»

On peut un élément ou une collection entière à un autre en utilisant l'opérateur «+»:

@Test fun whenJoinTwoCollections_thenSuccess () { val firstList = listOf("one", "two", "three") val secondList = listOf("four", "five", "six") val resultList = firstList + secondList assertEquals(6, resultList.size) assertTrue(resultList.contains("two")) assertTrue(resultList.contains("five")) }

3.3. L' opérateur «-»

De même, nous pouvons supprimer un ou plusieurs éléments en utilisant l'opérateur «-»:

@Test fun whenExcludeItems_thenRemoved () { val firstList = listOf("one", "two", "three") val secondList = listOf("one", "three") val resultList = firstList - secondList assertEquals(1, resultList.size) assertTrue(resultList.contains("two")) }

4. Autres méthodes

Enfin, nous explorerons quelques méthodes courantes de collecte. En Java, si nous voulions tirer parti des méthodes avancées, nous aurions besoin d'utiliser l' API Stream .

Dans Kotlin, nous pouvons trouver des méthodes similaires disponibles dans l'API Collections.

4.1. Tranchage

Nous pouvons obtenir une sous-liste à partir d'une liste donnée :

@Test fun whenSliceCollection_thenSuccess () { val theList = listOf("one", "two", "three") val resultList = theList.slice(1..2) assertEquals(2, resultList.size) assertTrue(resultList.contains("two")) }

4.2. Suppression

Nous pouvons facilement supprimer toutes les valeurs nulles d'une liste:

@Test fun whenFilterNullValues_thenSuccess () { val theList = listOf("one", null, "two", null, "three") val resultList = theList.filterNotNull() assertEquals(3, resultList.size) }

4.3. Filtration

Nous pouvons facilement filtrer les éléments de collection à l'aide de filter (), qui fonctionne de manière similaire à la méthode filter () de l' API Java Stream :

@Test fun whenFilterNonPositiveValues_thenSuccess () { val theList = listOf(1, 2, -3, -4, 5, -6) val resultList = theList.filter{ it > 0} assertEquals(3, resultList.size) assertTrue(resultList.contains(1)) assertFalse(resultList.contains(-4)) }

4.4. Goutte

Nous pouvons déposer les N premiers éléments:

@Test fun whenDropFirstItems_thenRemoved () { val theList = listOf("one", "two", "three", "four") val resultList = theList.drop(2) assertEquals(2, resultList.size) assertFalse(resultList.contains("one")) assertFalse(resultList.contains("two")) }

Nous pouvons supprimer les premiers éléments s'ils satisfont à la condition donnée:

@Test fun whenDropFirstItemsBasedOnCondition_thenRemoved () { val theList = listOf("one", "two", "three", "four") val resultList = theList.dropWhile{ it.length < 4 } assertEquals(2, resultList.size) assertFalse(resultList.contains("one")) assertFalse(resultList.contains("two")) }

4.5. Regroupement

Nous pouvons regrouper des éléments:

@Test fun whenGroupItems_thenSuccess () { val theList = listOf(1, 2, 3, 4, 5, 6) val resultMap = theList.groupBy{ it % 3} assertEquals(3, resultMap.size) assertTrue(resultMap[1]!!.contains(1)) assertTrue(resultMap[2]!!.contains(5)) }

4.6. Cartographie

Nous pouvons mapper tous les éléments en utilisant la fonction fournie:

@Test fun whenApplyFunctionToAllItems_thenSuccess () { val theList = listOf(1, 2, 3, 4, 5, 6) val resultList = theList.map{ it * it } assertEquals(4, resultList[1]) assertEquals(9, resultList[2]) }

Nous pouvons utiliser flatMap () pour aplatir les collections imbriquées. Ici, nous convertissons des chaînes en L ist et évitons de finir avec List :

@Test fun whenApplyMultiOutputFunctionToAllItems_thenSuccess () { val theList = listOf("John", "Tom") val resultList = theList.flatMap{ it.toLowerCase().toList() } assertEquals(7, resultList.size) }

4.7. Réduction

Nous pouvons effectuer une opération de pliage / réduction :

@Test fun whenApplyFunctionToAllItemsWithStartingValue_thenSuccess () { val theList = listOf(1, 2, 3, 4, 5, 6) val finalResult = theList.fold(0, {acc, i -> acc + (i * i)}) assertEquals(91, finalResult) }

4.8. Regrouper

Pour diviser une collection en morceaux d'une taille donnée, nous pouvons utiliser la méthode chunked () :

@Test fun whenApplyingChunked_thenShouldBreakTheCollection() { val theList = listOf(1, 2, 3, 4, 5) val chunked = theList.chunked(2) assertThat(chunked.size).isEqualTo(3) assertThat(chunked.first()).contains(1, 2) assertThat(chunked[1]).contains(3, 4) assertThat(chunked.last()).contains(5) }

Since the collection has five elements, the chunked(2) method call returns two collections with two elements each and one single-element collection.

It's also possible to map each chunk to something else after breaking up the collection:

@Test fun whenApplyingChunkedWithTransformation_thenShouldBreakTheCollection() { val theList = listOf(1, 2, 3, 4, 5) val chunked = theList.chunked(3) { it.joinToString(", ") } assertThat(chunked.size).isEqualTo(2) assertThat(chunked.first()).isEqualTo("1, 2, 3") assertThat(chunked.last()).isEqualTo("4, 5") }

After creating chunks of size 3, we convert each chunk to a comma-separated string.

4.9. Windowing

The windowed() function returns a list of element ranges by moving a sliding window of a given size over a collection of elements.

In order to better understand this, let's see how windowed(3) works on a collection of 6 elements:

At first, the window size is 3, therefore the first list would contain 1, 2, and 3. Then the sliding window moves one element further:

La fenêtre coulissante avance jusqu'à ce qu'elle ne parvienne pas à créer une autre liste de la taille donnée:

Cette séquence de transitions se manifeste dans le code Kotlin comme:

@Test fun whenApplyingWindowed_thenShouldCreateSlidingWindowsOfElements() { val theList = (1..6).toList() val windowed = theList.windowed(3) assertThat(windowed.size).isEqualTo(4) assertThat(windowed.first()).contains(1, 2, 3) assertThat(windowed[1]).contains(2, 3, 4) assertThat(windowed[2]).contains(3, 4, 5) assertThat(windowed.last()).contains(4, 5, 6) }

Par défaut, la fenêtre glissante se déplace d'un cran plus loin à chaque fois. Nous pouvons, bien sûr, changer cela en passant une valeur d'étape personnalisée:

@Test fun whenApplyingWindowedWithTwoSteps_thenShouldCreateSlidingWindowsOfElements() { val theList = (1..6).toList() val windowed = theList.windowed(size = 3, step = 2) assertThat(windowed.size).isEqualTo(2) assertThat(windowed.first()).contains(1, 2, 3) assertThat(windowed.last()).contains(3, 4, 5) }

La fonction windowed () , par défaut, crée toujours et uniquement des plages de la taille donnée. Pour changer cela, nous pouvons définir le paramètre partialWindows sur true :

@Test fun whenApplyingPartialWindowedWithTwoSteps_thenShouldCreateSlidingWindowsOfElements() { val theList = (1..6).toList() val windowed = theList.windowed(size = 3, step = 2, partialWindows = true) assertThat(windowed.size).isEqualTo(3) assertThat(windowed.first()).contains(1, 2, 3) assertThat(windowed[1]).contains(3, 4, 5) assertThat(windowed.last()).contains(5, 6) }

Semblable à la fonction chunked () , il est possible de mapper chaque plage à quelque chose d'autre:

@Test fun whenApplyingTransformingWindows_thenShouldCreateSlidingWindowsOfElements() { val theList = (1..6).toList() val windowed = theList.windowed(size = 3, step = 2, partialWindows = true) { it.joinToString(", ") } assertThat(windowed.size).isEqualTo(3) assertThat(windowed.first()).isEqualTo("1, 2, 3") assertThat(windowed[1]).isEqualTo("3, 4, 5") assertThat(windowed.last()).isEqualTo("5, 6") }

5. Conclusion

Nous avons exploré l'API Collections de Kotlin et certaines des méthodes les plus intéressantes.

Et, comme toujours, le code source complet peut être trouvé sur GitHub.