W3docs

Visão Geral do Java Collections Framework

Tour pelo Java Collections Framework — interfaces, implementações e algoritmos em java.util.

Quase todo programa acaba precisando guardar um grupo de coisas — pedidos aguardando envio, palavras de um documento, usuários online no momento, a fila de tarefas pendentes que uma thread trabalhadora vai processar. A resposta do Java para "onde coloco esse grupo" é o Collections Framework: um conjunto coordenado de interfaces em java.util, mais de uma dúzia de implementações por trás delas, e uma única classe utilitária de algoritmos (Collections) que opera sobre as interfaces, não sobre nenhuma implementação específica. Este capítulo é o mapa — o que há no framework, por que ele foi construído assim, e qual família usar em cada situação. Cada capítulo desta parte aprofunda um dos blocos desse mapa.

Por que um framework e não apenas classes

Antes do Java 1.2 existiam classes para grupos (Vector, Hashtable, Stack), mas não havia interface compartilhada — não era possível escrever um método que aceitasse "qualquer lista" e recebesse as três. O Collections Framework resolveu isso separando o que é um grupo (a interface) de como ele é armazenado (a implementação). O ganho fica evidente no dia a dia:

// You program against the interface, not the class.
List<String> names = new ArrayList<>();
// Later, swap in a different implementation without touching the rest of the code:
List<String> names = new LinkedList<>();

Todo método chamado em names é definido na interface List. A escolha entre ArrayList e LinkedList é uma decisão de desempenho, não de API. Também é possível escrever métodos como void print(List<String> xs) uma única vez e passar qualquer implementação.

As quatro interfaces raiz

O framework é organizado em torno de quatro interfaces raiz. Escolha aquela cujo contrato corresponde ao que seus dados precisam:

  • Collection<E> — a raiz. Um grupo de elementos E. Nada é dito sobre ordem, duplicatas ou indexação.
  • List<E> — uma coleção ordenada acessível por índice. Duplicatas permitidas. Pense em "array que cresce" ou "sequência encadeada." ArrayList, LinkedList, Vector.
  • Set<E> — uma coleção que proíbe duplicatas. Conjunto matemático. Pode ou não ser ordenado. HashSet, LinkedHashSet, TreeSet.
  • Map<K, V> — busca por chave→valor. Não é uma Collection (seus elementos são entradas, não valores simples), mas faz parte do framework. HashMap, LinkedHashMap, TreeMap.

Mais duas ficam ao lado de List e Set como especializações de Collection:

  • Queue<E> — coleção de "próximo da fila". FIFO por padrão. LinkedList, ArrayDeque, PriorityQueue.
  • Deque<E> — fila de duas pontas. Adiciona e remove em qualquer extremidade. ArrayDeque, LinkedList.

Toda classe de coleção da biblioteca padrão implementa ao menos uma dessas interfaces.

Escolha a família pelo comportamento, depois a classe pelo custo

A decisão tem duas camadas:

  1. O que os dados precisam? Ordenado com duplicatas → List. Sem duplicatas → Set. Busca por chave → Map. Produtor/consumidor → Queue ou Deque.
  2. Dentro da família, quais são os padrões de acesso? Acesso aleatório por índice → ArrayList. Muitas inserções/remoções na frente → LinkedList ou ArrayDeque. Iteração ordenada → TreeSet / TreeMap. Simplesmente "preciso de um conjunto rápido" → HashSet / HashMap.

Uma tabela de referência rápida para os principais casos:

NecessidadeUseNotas
Lista redimensionável, acesso aleatório rápidoArrayListO List padrão.
Lista com inserção/remoção frequente nas extremidadesArrayDeque (como fila similar a lista)Supera LinkedList na prática.
Set, contains/add/remove rápidosHashSetSem garantia de ordem.
Set com iteração previsívelLinkedHashSetIteração em ordem de inserção.
Set ordenadoTreeSetOperações O(log n).
Map, busca rápidaHashMapO Map padrão.
Map com iteração previsívelLinkedHashMapÚtil para caches (LRU).
Map ordenadoTreeMapChaves em ordem crescente.
Fila FIFOArrayDequeMais rápido que LinkedList.
Sempre remover o menor elementoPriorityQueueBaseado em heap.

Vector, Stack e Hashtable são as classes pré-1.2 — ainda no JDK por compatibilidade retroativa, mas não são mais a escolha certa em código novo. Seus substitutos modernos são abordados em capítulos próprios.

Generics tornam as coleções seguras em tipos

Toda interface e classe de coleção é genérica. Você a parametriza com o tipo do elemento na declaração, e o compilador passa a garantir isso:

List<String> names = new ArrayList<>();
names.add("Ada");
names.add(42);          // ❌ compile error — Integer is not a String
String first = names.get(0);   // no cast needed

O diamante <> à direita pede ao compilador que infira o tipo a partir do lado esquerdo — economiza digitação sem perder segurança. A parte anterior do livro (Generics) é o conjunto de regras por trás de tudo isso; o restante desta parte pressupõe que você a leu.

Os algoritmos vivem na classe Collections

Operações que não estão vinculadas a uma implementação específica — sort, shuffle, reverse, binary-search, min, max, frequency, wrappers não modificáveis — vivem na classe utilitária estática java.util.Collections. Atenção ao s no final: Collection (a interface) é um elemento; Collections (a classe) é o kit de ferramentas:

List<Integer> xs = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
Collections.sort(xs);                    // mutates xs
int idx = Collections.binarySearch(xs, 5);
List<Integer> ro = Collections.unmodifiableList(xs);

Dedicamos três capítulos no final desta parte a Collections — busca, ordenação e wrappers não modificáveis — porque a classe utilitária é onde grande parte do trabalho prático acontece.

Um passeio completo inicial

O programa abaixo seleciona um representante de cada família e demonstra as operações que você usará repetidamente. Não se preocupe em entender cada linha agora — cada classe aqui tem seu próprio capítulo. O objetivo é ver a forma do framework: mesmos nomes de métodos, mesmos padrões, mesmo modelo de iteração.

java— editable, runs on the server

Observe três coisas na saída:

  1. O Set silenciosamente descartou a duplicata "Effective Java". Esse é o contrato — nenhum código extra é necessário da sua parte.
  2. O Queue retornou os itens na ordem em que foram adicionados. offer enfileira, peek olha o topo sem remover, poll remove e retorna.
  3. O loop for-each funciona em toda Collection. Maps iteramos via entrySet(), keySet() ou values(), dependendo do que você quer.

Esse é o framework em miniatura.

Aviso

HashSet e HashMap não fazem nenhuma promessa sobre a ordem de iteração — a ordem que você vê na saída acima é um detalhe de implementação e pode variar entre versões da JVM ou execuções. Se você precisar de uma ordem estável, use LinkedHashSet/LinkedHashMap (ordem de inserção) ou TreeSet/TreeMap (ordem crescente). Nunca escreva código que dependa da ordem de iteração de um HashSet ou HashMap simples.

O que vem a seguir

Você viu o mapa. O restante da Parte 11 percorre cada região. O ponto de partida natural é a raiz da qual toda coleção herda — a própria interface Collection, onde métodos como add, remove, contains, size e iterator() são definidos de uma vez por todas.

Prática

Prática
Você precisa armazenar um grupo de palavras e responder rapidamente 'esta palavra está no grupo?' Duplicatas não são relevantes — `cat` ou aparece ou não aparece. Qual família do Collections Framework é a mais indicada?
Você precisa armazenar um grupo de palavras e responder rapidamente 'esta palavra está no grupo?' Duplicatas não são relevantes — `cat` ou aparece ou não aparece. Qual família do Collections Framework é a mais indicada?
Was this page helpful?