1. Introdução
Em algum momento, nós já lidamos com “arrays infinitos” — as listas. Vamos aprofundar nosso conhecimento e, para isso, vamos nos perguntar novamente o que é um array “clássico”. Se observarmos bem, ele lembra uma caixa de ferramentas com um número fixo de compartimentos. Suponha que a caixa tenha 10 compartimentos. Você ganhou a 11ª ferramenta, e agora? Vai precisar comprar outra caixa! Assim também um array tradicional tem tamanho fixo e, após ser criado, seu comprimento, seja qual for, não muda.
Se for preciso adicionar ou remover um elemento, é necessário criar um novo array e copiar os dados manualmente. Em um array é fácil e rápido encontrar um elemento pelo índice, mas inserir um elemento no meio do array não é simplesmente “inserir”, e sim “deslocar tudo para a direita”; ao remover, “deslocar tudo para a esquerda”. Isso é lento e inconveniente. Além disso, o array não guarda nenhuma “lógica” adicional: ele apenas mantém um conjunto de posições, e a ordenação, a busca por conteúdo ou a verificação de unicidade precisam ser feitas por meios externos.
Exemplo: lista dinâmica de alunos
Suponha que você esteja escrevendo um aplicativo para controle de alunos em uma turma. No início há 5 pessoas na turma, depois chega mais uma, depois alguém sai. Com um array, isso ficaria assim:
String[] students = new String[5];
students[0] = "Ivan";
students[1] = "Mariya";
// e assim por diante...
// Opa, chegou mais um aluno
// É preciso criar um novo array!
String[] newStudents = new String[6];
for (int i = 0; i < students.length; i++) {
newStudents[i] = students[i];
}
newStudents[5] = "Aleksey";
students = newStudents;
Confortável? Para dizer o mínimo, não. E se houver muitas operações assim? Aí já dá vontade de algo mais prático...
2. O que é uma coleção?
Uma coleção é um objeto que serve como um contêiner para armazenar um grupo de outros objetos (elementos). As coleções permitem adicionar, remover, iterar elementos e também executar outras operações: busca, ordenação, filtragem etc.
Em Java, todas as coleções implementam ou herdam da interface Collection (ou, no caso de mapeamentos — de Map). Coleção não é apenas “um monte de coisas”, e sim uma estrutura que fornece um conjunto conveniente e bem pensado de métodos para trabalhar com os elementos.
Por que coleções são objetos?
Porque as coleções são implementadas como classes; isso significa que você pode criar coleções de quaisquer objetos, combiná-las, herdá-las, estendê-las e usá-las nas suas classes e métodos.
Exemplo:
import java.util.ArrayList;
import java.util.List;
List<String> students = new ArrayList<>();
students.add("Ivan");
students.add("Mariya");
students.add("Aleksey");
Voilà! Agora você pode adicionar quantos alunos quiser, sem se preocupar com o tamanho do array.
3. Tarefas típicas que as coleções resolvem
As coleções são um canivete suíço para trabalhar com dados. Veja que tipos de tarefas elas permitem resolver:
- Armazenamento de listas dinâmicas de dados: Por exemplo, lista de alunos, tarefas em um planner, mensagens em um chat.
- Busca e filtragem: Encontrar rapidamente um elemento, verificar sua existência, obter todos os elementos que atendem a um determinado critério.
- Ordenação: Ordenar facilmente elementos por um critério desejado.
- Remoção e adição de elementos: Inserção e remoção de elementos em qualquer lugar da coleção sem precisar copiar arrays manualmente.
- Agrupamento por chave: Por exemplo, uma agenda telefônica, em que cada nome corresponde a um número de telefone.
- Garantia de unicidade: Por exemplo, o conjunto de todas as palavras únicas em um texto.
Exemplo: agenda telefônica
Com array:
- Como encontrar o número pelo nome? Será preciso percorrer o array e comparar os nomes.
- Como adicionar um novo par? Será preciso expandir o array.
- Como garantir que os nomes não se repitam? Ainda mais complicado.
Com coleção:
- Usamos Map<String, String> — e tudo funciona pronto para uso.
4. Visão geral dos principais tipos de coleções
Em Java, as coleções se dividem em três grupos principais:
| Tipo de coleção | Interface/Classe | Para que é usada |
|---|---|---|
| Lista | List, ArrayList | Conjunto ordenado de elementos, permite duplicatas, acesso por índice |
| Conjunto | Set, HashSet | Armazena apenas elementos únicos, a ordem não é garantida |
| Mapa | Map, HashMap | Armazena pares chave-valor, busca rápida pela chave |
Listas (List)
- Coleções ordenadas, permitem duplicatas.
- É possível obter um elemento pelo índice.
- Exemplos: ArrayList, LinkedList.
Conjuntos (Set)
- Armazenam apenas elementos únicos.
- Sem acesso por índice.
- Exemplos: HashSet, TreeSet.
Mapas (Map)
- Armazenam pares chave-valor.
- Busca rápida pela chave.
- Exemplos: HashMap, TreeMap.
Esquema visual (bem aproximado):
+------------------+ +-------------------+ +---------------------+
| List | | Set | | Map |
|------------------| |-------------------| |---------------------|
| [a, b, c, d, a] | | {a, b, c, d} | | {a=1, b=2, c=3} |
| Indexação: sim | | Indexação: não | | Busca por chave |
| Duplicatas: sim | | Duplicatas: não | | Chaves únicas |
+------------------+ +-------------------+ +---------------------+
5. Detalhes úteis
Quando usar qual coleção?
List — quando a ordem dos elementos é importante, são necessárias duplicatas e é preciso acesso por índice (por exemplo, lista de tarefas, histórico de mensagens).
Set — quando você precisa apenas de elementos únicos e a ordem não importa (por exemplo, o conjunto de usuários únicos).
Map — quando é necessário associar chaves a valores (por exemplo, uma agenda telefônica em que o nome é a chave e o telefone é o valor).
Analogias do cotidiano
List — fila no refeitório: quem chega primeiro é atendido primeiro; é possível entrar na fila várias vezes (duplicatas).
Set — lista de convidados de uma festa: cada convidado aparece apenas uma vez (unicidade).
Map — agenda de endereços: cada nome tem seu telefone.
Guia rápido: coleções vs arrays
| Array (int[]) | Coleção (List<Integer>) | |
|---|---|---|
| Tamanho | Fixo | Dinâmico |
| Inserção de elemento | Trabalhosa | Fácil: add() |
| Remoção de elemento | Trabalhosa | Fácil: remove() |
| Busca por valor | Varredura manual | Métodos: contains(), etc. |
| Ordenação | Via Arrays.sort() | Via Collections.sort(), métodos das coleções |
| Suporte a unicidade | Não | Por meio de Set |
| Pares chave-valor | Não | Por meio de Map |
6. Relação das coleções com POO
Coleções são objetos que implementam determinadas interfaces (List, Set, Map). Isso significa que você pode:
- Armazenar nas coleções quaisquer objetos, inclusive instâncias das suas próprias classes.
- Criar coleções de coleções (por exemplo, lista de listas).
- Usar coleções como parâmetros e valores de retorno de métodos.
- Estender a funcionalidade das coleções por meio de herança e composição.
Exemplo: coleção de objetos da sua classe
import java.util.ArrayList;
import java.util.List;
class Student {
String name;
int age;
// Construtor, getters/setters etc.
}
public class Main {
public static void main(String[] args) {
List<Student> group = new ArrayList<>();
group.add(new Student("Ivan", 20));
group.add(new Student("Mariya", 21));
// e assim por diante...
}
}
7. Erros comuns ao trabalhar com coleções
Erro nº 1: uso de coleções sem tipo (raw types).
Se você escreve ArrayList list = new ArrayList(), então, ao adicionar qualquer objeto (por exemplo, strings e números misturados), o compilador não reclamará, mas depois, ao tentar obter um elemento e convertê-lo para o tipo necessário, você pode receber um erro em tempo de execução (ClassCastException). Sempre use generics: ArrayList<String> list = new ArrayList<>().
Erro nº 2: esqueceu de importar a classe necessária.
Se você vir o erro “cannot find symbol”, verifique se no início do arquivo há a linha import java.util.ArrayList; ou o import necessário para a sua coleção.
Erro nº 3: confundir coleções com arrays.
Coleção não é array! Uma coleção não tem o campo length; em vez disso, use o método size(). Um array não tem o método add(); uma coleção não tem o operador [] para acesso por índice (apenas listas com get(index)).
Erro nº 4: presumir que a ordem dos elementos sempre é preservada.
Se você usar Set ou Map, a ordem dos elementos não é garantida (a não ser que você use implementações específicas como LinkedHashSet ou TreeMap). Para dados ordenados, use List ou coleções apropriadas.
Erro nº 5: usar tipos primitivos em coleções.
As coleções podem armazenar apenas objetos, não tipos primitivos. Ou seja, não é possível criar List<int>, apenas List<Integer>. Não se esqueça das classes wrapper!
GO TO FULL VERSION