Panoramica dell'API delle raccolte Kotlin

1. Panoramica

In questo breve tutorial, introdurremo l'API delle raccolte di Kotlin e discuteremo i diversi tipi di raccolta in Kotlin e alcune operazioni comuni sulle raccolte.

2. Raccolta vs raccolta mutevole

Per prima cosa, diamo un'occhiata ai diversi tipi di raccolte in Kotlin. Vedremo come inizializzare i tipi base di raccolte.

L' interfaccia Collection supporta metodi di sola lettura mentre MutableCollection supporta metodi di lettura / scrittura.

2.1. Elenco

Possiamo creare una semplice lista di sola lettura usando il metodo listOf () e leggere-scrivere MutableList usando mutableListOf () :

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

2.2. Impostato

Allo stesso modo possiamo creare un Set di sola lettura usando il metodo setOf () e leggere-scrivere MutableSet usando mutableSetOf () :

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

2.3. Carta geografica

Possiamo anche creare una mappa di sola lettura usando il metodo mapOf () e leggere-scrivere MutableMap usando 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. Operatori utili

L'API Collections di Kotlin è molto più ricca di quella che possiamo trovare in Java: viene fornita con una serie di operatori sovraccarichi.

3.1. L' operatore " in"

Possiamo usare l'espressione " x in collection " che può essere tradotta in collection.contains (x) :

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

3.2. L' operatore "+"

Possiamo un elemento o un'intera collezione a un altro utilizzando l'operatore "+":

@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' operatore "-"

Allo stesso modo, possiamo rimuovere uno o più elementi utilizzando l'operatore "-":

@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. Altri metodi

Infine, esploreremo alcuni metodi comuni per la raccolta. In Java, se volessimo sfruttare metodi avanzati, avremmo bisogno di utilizzare Stream API.

In Kotlin, possiamo trovare metodi simili disponibili nell'API Collections.

4.1. Affettare

Possiamo ottenere una sottolista da una data lista:

@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. Rimozione

Possiamo rimuovere facilmente tutti i valori nulli da un elenco:

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

4.3. Filtraggio

Possiamo filtrare facilmente gli elementi della raccolta utilizzando filter (), che funziona in modo simile al metodo filter () dall'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. Caduta

Possiamo rilasciare i primi N elementi:

@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")) }

Possiamo eliminare i primi articoli se soddisfano la condizione data:

@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. Raggruppamento

Possiamo raggruppare elementi:

@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. Mappatura

Possiamo mappare tutti gli elementi utilizzando la funzione fornita:

@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]) }

Possiamo usare flatMap () per appiattire le raccolte annidate. Qui, stiamo convertendo le stringhe di L ist ed evitando di finire con la lista :

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

4.7. Riduzione

Possiamo eseguire operazioni di piegatura / riduzione :

@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. Chunking

Per suddividere una raccolta in blocchi di una determinata dimensione, possiamo utilizzare il metodo 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 finestra scorrevole si sposta in avanti finché non riesce a creare un altro elenco della dimensione specificata:

Questa sequenza di transizioni si manifesta nel codice Kotlin come:

@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) }

Per impostazione predefinita, la finestra scorrevole si sposta di un passo avanti ogni volta. Possiamo, ovviamente, cambiarlo passando un valore di passaggio personalizzato:

@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 funzione windowed () , per impostazione predefinita, crea sempre e solo intervalli della dimensione data. Per cambiarlo, possiamo impostare il parametro partialWindows su 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) }

Simile alla funzione chunked () , è possibile mappare ogni intervallo su qualcos'altro:

@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. conclusione

Abbiamo esplorato l'API delle raccolte di Kotlin e alcuni dei metodi più interessanti.

E, come sempre, il codice sorgente completo può essere trovato su GitHub.