Colecções Imutáveis Kotlin
1. Introdução
Neste tutorial,we’ll be looking at how to create immutable collections in Kotlin.
Primeiro, vamosexplore the types of immutability, bem como o que o Kotlin fornece como padrão. Então, veremos comoleverage Google’s Guava library to create truly immutable collections.
Como alternativa, também examinaremos oKotlinx Immutable Collections Library for Kotlin.
2. Dependências
Antes de criar nossas coleções imutáveis, precisaremos importar Guava e a Biblioteca de coleções imutáveis.
2.1. Maven
org.jetbrains.kotlinx
kotlinx-collections-immutable
0.1
com.google.guava
guava
27.1-jre
false
kotlinx
bintray
https://dl.bintray.com/kotlin/kotlinx
2.2. Gradle
repositories {
maven {
url "https://dl.bintray.com/kotlin/kotlinx"
}
}
// https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-collections-immutable
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-collections-immutable', version: '0.1'
// https://mvnrepository.com/artifact/com.google.guava/guava
compile group: 'com.google.guava', name: 'guava', version: '27.1-jre'
3. Tipos de Imutabilidade
Antes de começar, vamos dar uma olhada emdifferent types of immutability a collection can possess:
-
Mutable - O conteúdo da lista pode ser alterado livremente
-
Read-Only - O conteúdo da coleção não deve ser alterado. No entanto, os dados subjacentes podem ser alterados
-
Immutable - Nada pode alterar o conteúdo da coleção
Coleções imutáveis têm muitos usos na programação. Por exemplo, podemosshare them freely between different threads sem risco de entrar em condições de corrida. Além disso,immutable collection implementations are always more memory-efficient do que suas alternativas mutáveis.
Além disso, o uso de coleções imutáveis é umgreat defensive programming technique - garantindo que não faremos alterações indesejadas em nossos dados.
4. Colecções Kotlin
In Kotlin, all non-mutable collections, such as List, are compile-time read-only by default, e não imutável. Embora as interfaces definidas não suportem métodos para alterar dados na coleção, os dados subjacentes ainda podem ser alterados.
Vamos demonstrar isso tentando alterar nossoList somente leitura:
@Test
fun givenReadOnlyList_whenCastToMutableList_checkNewElementsAdded(){
val list: List = listOf("This", "Is", "Totally", "Immutable")
(list as MutableList)[2] = "Not"
assertEquals(listOf("This", "Is", "Not", "Immutable"), list)
}
Em nosso exemplo acima, criamos uma novaList e atribuímos a variávellist . Por padrão,List interface de Kotlin é somente leitura e não nos permite adicionar novos elementos à nossa lista. No entanto, ao lançarList to aMutableList, estamos livres para adicionar novos elementos por meio de seu métodoadd.
5. Goiaba
For absolute immutability, we can make use of Guava’s set of immutable collections. Guava fornece versões imutáveis de muitas coleções Java, incluindohttps://github.com/google/guava/wiki/ImmutableCollectionsExplained#DetailsImmutableMap.
Vamos dar uma olhada em uma ação deImmutableList in, porusing the ImmutableList.of method:
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()
@Test
fun givenImmutableList_whenAddTried_checkExceptionThrown() {
val list: List = ImmutableList.of("I", "am", "actually", "immutable")
ee.expect(UnsupportedOperationException::class.java)
(list as MutableList).add("Oops")
}
Em nosso exemplo, podemos ver que mesmo com uma conversão paraMutableList, nossa lista resiste à mutação. Rather than accept the new element, an UnsupportedOperationException is thrown at runtime.
A goiaba também fornece métodos alternativos para instanciar listas imutáveis.
5.1. CopyOf
A seguir, vamos ver como instanciar umImmutableList de um mutável criado anteriormente. To achieve this, we can make use of the copyOf method, que leva outra coleção como argumento:
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()
@Test
fun givenMutableList_whenCopiedAndAddTried_checkExceptionThrown(){
val mutableList : List = listOf("I", "Am", "Definitely", "Immutable")
(mutableList as MutableList)[2] = "100% Not"
assertEquals(listOf("I", "Am", "100% Not", "Immutable"), mutableList)
val list: List = ImmutableList.copyOf(mutableList)
ee.expect(UnsupportedOperationException::class.java)
(list as MutableList)[2] = "Really?"
}
Aqui, criamos uma lista totalmente mutável com o uso do métodolistOf. Em seguida, criamos um imutável, com o uso do métodocopyOf . Finalmente, vemos que nosso código lança uma exceção quando um elemento é adicionado ao nossoImmutableList.
5.2. Um construtor acessível
Finalmente, vamos dar uma olhada nos construtores úteis que o Guava fornece para construir coleções imutáveis. Neste exemplo, vamos criar umImmutableSet. The https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/ImmutableSet.Builder.htmluilder provides all the fundamental methods for adding new single elements as well as copies of other collections:
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()
@Test
fun givenImmutableSetBuilder_whenAddTried_checkExceptionThrown(){
val mutableList : List = ArrayList(listOf("Hello", "example"))
val set: ImmutableSet = ImmutableSet.builder()
.add("I","am","immutable")
.addAll(mutableList)
.build()
assertEquals(setOf("Hello", "example", "I", "am", "immutable"), set)
ee.expect(UnsupportedOperationException::class.java)
(set as MutableSet).add("Oops")
}
Em nosso exemplo acima, construímos uma classeImmutableSet ofStrings de goiabaImmutableSet.Builder . Primeiro, adicionamos algunssingle Strings using the add method before adding the contents of mutableList using the builder’s addAll method.
Após validar o conteúdo, podemos ver que, como esperado, uma tentativa de adicionar mais elementos resulta em uma exceção.
6. Biblioteca de coleções imutáveis da Kotlinx
A resposta da JetBrain para a natureza somente leitura das coleções de Kotlin é oKotlinx Immutable Collections Library - que bocado, vamos chamá-lo de KICL para breve. KICLprovides immutable collection interfaces and implementation prototypes for Kotlin.
Pesando apenas uma fração dos 2,6 MB do Guava, KICLprovides a lightweight alternative to Guava quando precisamos apenas de um pouco de imutabilidade em nosso aplicativo.
Vamos dar uma olhada rápida nesta biblioteca em ação:
@Rule
@JvmField
var ee : ExpectedException = ExpectedException.none()
@Test
fun givenKICLList_whenAddTried_checkExceptionThrown(){
val list: ImmutableList = immutableListOf("I", "am", "immutable")
list.add("My new item")
assertEquals(listOf("I", "am", "immutable"), list)
}
A biblioteca de coleções imutáveis do Kotlinx funciona de maneira um pouco diferente das coleções de Guava. Como podemos ver acima,rather than throwing an UnsupportedOperationException, there is simply no new element added to the ImmutableList.
7. Conclusão
Neste artigo, vimos o que Kotlin oferece em termos de coleções imutáveis.
Em seguida, demos um mergulho profundo nas coleções imutáveis que o Guava do Google pode nos oferecer e na Biblioteca de coleções imutáveis Kotlinx
Todos os trechos de código podem ser encontradosover on GitHub.