8  Listas e coleções

Armazenar quantidades variáveis de dados

8.1 Objetivos de aprendizagem

Ao concluir este capítulo, você deverá ser capaz de:

  • explicar a diferença entre array e lista;
  • declarar uma variável pelo contrato List;
  • adicionar, consultar, alterar e remover elementos;
  • percorrer uma lista sem acessar índices inválidos;
  • usar generics para obter segurança de tipos.

8.2 List e ArrayList

Lista com elementos oi e ajuda recebendo o elemento dica e depois removendo oi.

Uma lista pode crescer e diminuir durante a execução.

Arrays têm tamanho fixo. Uma ArrayList pode crescer ou diminuir durante a execução. Prefira declarar a variável com a interface List:

import java.util.ArrayList;
import java.util.List;

List<String> historico = new ArrayList<>();
historico.add("oi");
historico.add("ajuda");

O tipo entre < > informa quais elementos são aceitos. List<String> rejeita números e outros tipos em tempo de compilação.

8.3 Operações essenciais

historico.add("dica");
String primeira = historico.get(0);
historico.set(0, "OI");
historico.remove("dica");

System.out.println(historico.size());
System.out.println(historico.isEmpty());
System.out.println(historico.contains("ajuda"));

Índices válidos vão de zero até size() - 1. Se a posição vier da pessoa usuária, valide-a antes de chamar get, set ou remove.

8.4 Exemplo completo

import java.util.ArrayList;
import java.util.List;

public class Capitulo07Colecoes {
    public static void main(String[] args) {
        List<String> historico = new ArrayList<>();
        historico.add("oi");
        historico.add("ajuda");
        historico.add("dica");

        for (String mensagem : historico) {
            System.out.println("Usuário: " + mensagem);
        }

        String ultima = historico.get(historico.size() - 1);
        System.out.println("Última mensagem: " + ultima);
        System.out.println("Total: " + historico.size());
    }
}

8.5 Cópias e exposição de estado

Se uma classe devolver sua lista interna, código externo poderá alterá-la sem passar pelas regras da classe. Uma cópia somente para leitura evita esse problema:

public List<String> getHistorico() {
    return List.copyOf(historico);
}

8.6 Autoboxing

Coleções armazenam objetos. Para números inteiros, use Integer, não int:

List<Integer> pontuacoes = new ArrayList<>();
pontuacoes.add(10); // int convertido para Integer

A conversão automática entre int e Integer é chamada autoboxing e unboxing.

8.7 Evolução do projeto: versão 7

Substitua o contador isolado por uma lista de mensagens válidas. O comando historico deve consultar a lista, mas não entrar nela; assim, “total de mensagens” significa apenas mensagens da pessoa usuária processadas antes da consulta.

O exemplo completo está em examples/src/Capitulo07Colecoes.java.

8.8 Prática verificável

Implemente métodos para:

  1. registrar mensagem não vazia;
  2. devolver a última mensagem;
  3. devolver, no máximo, as três mensagens mais recentes;
  4. limitar o histórico a dez itens.

Casos de teste:

Estado Resultado esperado
lista vazia mensagem “Sem histórico”
dois itens os dois aparecem, na ordem
doze inserções com limite dez apenas as dez últimas permanecem
DicaEscolha da estrutura

Use array quando o tamanho fizer parte da regra. Use List quando a quantidade variar durante a execução.