O que é?

Lista é a estrutura de dados que representa listas ordenadas de itens.

Em Kotlin temos duas interfaces para representar listas: List e MutableList.

Por que é útil?

Listas são utilizadas na maioria das aplicações profissionais, sendo o conhecimento dessa estrutura de dados fundamental para o programador que deseja atuar profissionalmente.

Características

Veja a seguir as características de uma lista criada utilizando a interface List.

  • List é a interface padrão para criação de listas;
  • List é imutável, ou seja, uma vez criada a lista nenhum item pode ser adicionado ou removido dela;
  • Por ser imutável, List não possui métodos para alteração da lista, como add ou remove, por exemplo.

Veja a seguir as características de uma lista criada utilizando a interface MutableList.

  • MutableList é a interface para listas mutáveis, nas quais podemos adicionar ou remover itens;
  • Por ser mutável, MutableList possui métodos que modificam a lista, como add e remove, por exemplo.

Como utilizar: sintaxe

Para criar uma lista imutável usamos a função listOf, que retorna uma List, conforme apresentado no Código 1.


  val nomesProdutosPromocao: List<String> = listOf("Acem 1k", "Picanha 1k")
  
Código 1. Criando uma lista imutável de produtos

Para criar uma lista mutável, que pode receber/remover itens, usamos a função mutableListOf, que retorna uma MutableList, conforme apresentado no Código 2.


  val nomesProdutosPromocao: List<String> = mutableListOf("Acem 1k", "Picanha 1k")
  
Código 2. Criando uma lista mutável de produtos

List - Exemplo prático

Veremos agora um exemplo prático de como lidar com listas em Kotlin.

Para utilizar a classe List não é necessário instalar nenhuma dependência ou realizar configurações especiais, uma vez que ela pertence à biblioteca padrão (Kotlin Standard Library).

Antes de prosseguir vale destacar que usaremos a classe Produto (Código 3) nos exemplos a seguir.


  data class Produto(val codigo: String, var valor: Double)
  
Código 3. Classe Produto

Exemplo 1 - Lista de objetos

A função listOf, vista anteriormente pode receber objetos como argumento, como vemos no Código 4.


  val produtos = listOf(
      Produto("Java101", 29.99),
      Produto("Spring101", 59.99),
  )
  
Código 4. Criando uma lista com listOf

Note que quando usamos listOf dessa forma não é necessário informar o tipo da variável produtos como ": List<Produto>", uma vez que o compilador pode reconhecer o tipo da lista através dos itens dela.

Exemplo 2 - Iterando uma lista com forEach

Para iterar uma lista usamos comumente a função forEach, como vemos no Código 5.


  produtos.forEach {
      println(it.codigo)
  }
  
Código 5. Como iterar uma lista
Aprenda mais sobre a função forEach.

Tanto List quanto MutableList possuem o método forEach.

Exemplo 3 - List é imutável

Listas em Kotlin são imutáveis por padrão. Isso quer dizer que uma lista não pode ser alterada, receber ou perder itens, uma vez criada.

O Código 6 gera o erro Unresolved reference: add, pois List não possui função para isso.


  produtos.add(Produto("C#101", 19.99))
  
Código 6. Erro ao tentar inserir um item na lista

O mesmo erro ocorrerá ao tentar usar métodos para remover itens da lista, como removeAt, entre outros.

Para que tais operações sejam realizadas em uma lista ela deve ser mutável.

Veremos como criar listas mutáveis no próximo exemplo.

MutableList

Exemplo 1 - Criando uma lista mutável

Para criar uma lista, vazia ou não, e depois adicionar nela alguns itens devemos usar a função mutableListOf em lugar de listOf. A função mutableListOf cria uma lista mutável de itens, como vemos no Código 7.


  val produtos = mutableListOf<>(
      Produto("Java101", 29.99),
      Produto("Spring101", 59.99),
  )
  
Código 7. Criando uma lista mutável de itens

A função mutableListOf retorna uma instância de MutableList, que suporta operações que a modifiquem como adicionar ou remover itens, por exemplo.

Exemplo 2 - Transformando uma lista mutável em imutável

Uma lista mutável (MutableList) pode ser transformada em imutável (List) em uma função, como vemos no Código 8.


  val produtos = mutableListOf<>(
      Produto("Java101", 29.99),
      Produto("Spring101", 59.99),
  )
   
  fun getProdutos() : List<Produto> = produtos
  
Código 8. Retornando uma lista imutável de uma lista mutável

Dessa forma, a lista retornada por getProdutos servirá apenas para visualização dos itens.

Exemplo 3 - Adicionando um elemento na lista

Para adicionar itens em uma lista usamos a função add, como mostra o Código 9.


  produtos.add(Produto("C#101", 19.99))
  
Código 9. Retornando uma lista imutável de uma lista mutável

Lembre-se que apenas instâncias de MutableList possuem essa função.

Exemplo 4 - Adicionando múltiplos elementos em uma lista

É possível ainda adicionar uma lista a outra usando a função addAll, como mostra o Código 10.


  val produtos2 = mutableListOf(
      Produto("C#101", 29.99),
      Produto("Blazor101", 59.99),
  )
   
  produtos.addAll(produtos2)
  
Código 10. Adicionando uma lista a outra

No Código 10 todos os itens na lista produtos2 serão adicionados na lista produtos.

Lembre-se que apenas instâncias de MutableList possuem essa função.

Exemplo 5 - Removendo um elemento da lista pela posição

Para remover o item específico de uma lista podemos usar as funções removeAt, informando a posição do item, como mostra o Código 11.


  produtos.removeAt(1)
  
Código 11. Removendo o item de uma lista

Caso a posição informada não exista a exceção IndexOutOfBoundsException será lançada.

Lembre-se que apenas instâncias de MutableList possuem essa função.

Exemplo 6 - Removendo um elemento da lista pelo objeto

Uma outra forma de remover o item de uma lista é informando o objeto a ser removido, como visto no Código 12.


  val android202 = Produto("Android202", 14.99)
  produtos.add(android202)
  produtos.remove(android202)
  
Código 12. Removendo o item de uma lista

Diferente de removeAt (Exemplo 7), remove falha amigavelmente, retornando true se o item foi encontrado e removido ou false caso contrário.

Lembre-se que apenas instâncias de MutableList possuem essa função.

Exemplo 7 - Mutabilidade de referências para o mesmo objeto

Uma lista imutável gerada a partir de uma lista mutável é atualizada quando a lista mutável muda, uma vez que ambas apontam para o mesmo objeto.

Por exemplo, observe o Código 13.


  val produtos = mutableListOf(
      Produto("Java101", 29.99),
      Produto("Spring101", 59.99),
  )
   
  fun retornaProdutos(): List<Produto> = produtos
   
  fun main(args: Array<String>) {
      val produtosImutavel = retornaProdutos()
   
      produtos.add(Produto("C#101", 11.99))
   
      produtosImutavel.forEach {
          println(it.codigo)
      }
   
      produtos.forEach {
          println(it.codigo)
      }
  }
  
Código 13. Referências para o mesmo objeto em memória

Ambas as variáveis produtos e produtosImutavel apontam para o mesmo objeto. Dessa forma, quando na Linha 13 um novo produto é adicionado na lista, tanto produtos quanto produtosImutavel passam a armazená-lo.

Conclusão

A princípio, criar listas imutáveis pode parecer sem utilidade, uma vez que listas servem para armazenar itens. Contudo, conforme avançamos nos estudos, principalmente em boas práticas, descobrimos que quanto menos as coisas mudam mais facilmente são testadas e mais dificilmente erros acontecem.

Listas imutáveis são úteis, principalmente quando desejamos apenas apresentar para o usuário alguns valores, sem que, para isso, tenhamos que correr o risco de, por acidente, adicionar ou remover itens dela. Usar listas imutáveis sempre que possível e listas mutáveis sempre que necessário é uma boa prática de programação.