1. Classe ArrayList
Em Java, a interface List é um contrato: “Sou uma coleção ordenada de elementos, e é possível obter um elemento pelo número (índice)”.
Propriedades-chave da lista (List):
- Os elementos são armazenados em uma ordem definida (ao contrário de um conjunto).
- É possível armazenar elementos duplicados (por exemplo: duas vezes "João").
- Você pode acessar um elemento pelo índice: o primeiro elemento — índice 0, o segundo — 1 e assim por diante.
- É possível adicionar e remover elementos em qualquer posição da lista.
A implementação mais popular da interface List é a ArrayList. Por baixo dos panos, ela usa um array normal e se expande automaticamente conforme os dados crescem.
Como criar um ArrayList?
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
// Criamos uma lista de strings
List<String> students = new ArrayList<>();
}
}
Explicação
- List<String> é uma variável do tipo “lista de strings”. Declaramos a variável via interface e criamos o objeto por meio da classe concreta (ArrayList).
- Os colchetes angulares <String> definem o tipo dos elementos da lista (generics).
Métodos principais de ArrayList (e de qualquer List):
- add(element) — adiciona um elemento ao final da lista.
- add(index, element) — insere um elemento em um índice específico.
- get(index) — obtém o elemento pelo índice.
- set(index, element) — substitui o elemento pelo índice.
- remove(index) — remove o elemento pelo índice.
- remove(Object) — remove o primeiro elemento encontrado igual ao objeto passado.
- size() — informa a quantidade de elementos na lista.
Exemplo: Trabalhando com a lista de estudantes
import java.util.ArrayList;
import java.util.List;
public class StudentListDemo {
public static void main(String[] args) {
List<String> students = new ArrayList<>();
// Adiciona estudantes
students.add("João");
students.add("Pedro");
students.add("Maria");
// Exibe todos os estudantes
System.out.println("Lista de estudantes: " + students);
// Obtém o primeiro estudante
String first = students.get(0);
System.out.println("Primeiro estudante: " + first);
// Altera o nome do segundo estudante
students.set(1, "Paulo");
System.out.println("Após a alteração: " + students);
// Remove a Maria
students.remove("Maria");
System.out.println("Após remover a Maria: " + students);
// Tamanho da lista
System.out.println("Total de estudantes: " + students.size());
}
}
Resultado:
Lista de estudantes: [João, Pedro, Maria]
Primeiro estudante: João
Após a alteração: [João, Paulo, Maria]
Após remover a Maria: [João, Paulo]
Total de estudantes: 2
Como isso se relaciona com o nosso aplicativo?
Suponha que temos um aplicativo para controle de tarefas de um estudante. Agora podemos armazenar a lista de tarefas como List<String>, e não como array, e adicionar novas tarefas dinamicamente.
2. Classe LinkedList: quando a velocidade de inserção e remoção importa
LinkedList é uma implementação alternativa de lista. É estruturada como uma cadeia duplamente ligada: cada nó conhece os elementos anterior e seguinte. Como em uma composição de trem: inserir um “vagão” no meio é rápido e não exige reorganizar toda a composição.
Criação de LinkedList
import java.util.LinkedList;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<String> tasks = new LinkedList<>();
}
}
Características do LinkedList
- Inserção e remoção rápidas no início e no meio da lista.
- Acesso lento por índice (para encontrar o 100º elemento, é preciso percorrer a cadeia).
- Indicado quando você adiciona/remove elementos com frequência não só no final, mas também no início ou no meio.
Exemplo: Usando LinkedList
import java.util.LinkedList;
import java.util.List;
public class TaskListDemo {
public static void main(String[] args) {
List<String> tasks = new LinkedList<>();
tasks.add("Acordar");
tasks.add("Tomar café da manhã");
tasks.add("Ir para as aulas");
// Adiciona uma tarefa no início
tasks.add(0, "Colocar o despertador");
System.out.println("Lista de tarefas: " + tasks);
// Remove a primeira tarefa (a mais antiga)
tasks.remove(0);
System.out.println("Após remover a primeira tarefa: " + tasks);
}
}
3. Comparação entre ArrayList e LinkedList
| Critério | |
|
|---|---|---|
| Base | Array | Lista duplamente ligada |
| Acesso rápido por índice | Sim (O(1)) | Não (O(n)) |
| Inserção/remoção rápida no início/meio | Não (O(n)) | Sim (O(1) — se houver referência) |
| Inserção/remoção rápida no final | Sim (geralmente O(1)) | Sim (O(1)) |
| Memória | Consome menos memória | Mais (referências adicionais para vizinhos) |
| Cenários típicos | Acesso frequente por índice | Inserções/remoções frequentes |
Regra simples:
- Precisa de acesso rápido por índice — use ArrayList.
- Adiciona/remove com frequência no início ou no meio — use LinkedList.
4. Operações típicas com listas
Iteração dos elementos da lista
Laço for clássico
for (int i = 0; i < students.size(); i++) {
System.out.println("Estudante #" + i + ": " + students.get(i));
}
Laço for-each (a forma mais popular)
for (String name : students) {
System.out.println("Nome: " + name);
}
Expressão lambda (Java 8+)
students.forEach(name -> System.out.println("Nome: " + name));
Busca de elementos
- contains(element) — retorna true se o elemento estiver na lista.
- indexOf(element) — retorna o índice da primeira ocorrência do elemento, ou -1 se não for encontrado.
if (students.contains("João")) {
System.out.println("João está na lista!");
}
int index = students.indexOf("João");
System.out.println("Índice do João: " + index);
Limpeza da lista
clear() — remove todos os elementos.
students.clear();
System.out.println("Lista após a limpeza: " + students);
5. Quando usar ArrayList e quando LinkedList?
É mais simples pensar assim: ArrayList é boa onde você precisa acessar rapidamente os elementos por índice e a lista muda com pouca frequência. Por exemplo, uma lista longa de usuários ou um histórico de mensagens — principalmente leitura.
LinkedList, por outro lado, é útil quando você insere ou remove elementos constantemente no início/meio. Pode ser uma fila, uma pilha ou um histórico de desfazer ações.
Na prática, a ArrayList é usada com muito mais frequência. Já a LinkedList fica como “ferramenta para quando precisar”: fica na gaveta, mas às vezes é exatamente o que você precisa.
6. Erros comuns ao trabalhar com listas
Erro nº 1: Acesso fora dos limites da lista. A situação mais comum é acessar um índice inexistente. Se a lista tem três elementos e você escreve students.get(5), receberá IndexOutOfBoundsException. Antes de acessar, verifique size().
Erro nº 2: Remoção de elemento durante a iteração. Ao iterar com for-each e remover elementos ao mesmo tempo, ocorrerá ConcurrentModificationException. Para remoções complexas, use um laço por índice ou Iterator.
Erro nº 3: Comparação incorreta de objetos. Se você armazena seus próprios objetos (por exemplo, Student), os métodos contains e remove dependem de equals. Se não o sobrescrever, a comparação será por referência, não por conteúdo.
Erro nº 4: Uso de tipos brutos (raw types). Não escreva List list = new ArrayList() — sempre informe o tipo dos elementos: List<String> list = new ArrayList<>(). Generics protegem contra erros e deixam o código mais claro.
GO TO FULL VERSION