Colecções Imutáveis ​​Kotlin

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:

  1. Mutable - O conteúdo da lista pode ser alterado livremente

  2. Read-Only - O conteúdo da coleção não deve ser alterado. No entanto, os dados subjacentes podem ser alterados

  3. 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.