Java Cola de Coleções

Uma página para consultar quando você precisar escolher uma coleção ou lembrar o nome de um método. Primeiro a tabela "qual usar", depois os métodos de List, Set, Map e Deque, com exemplos e resultados reais do JShell. Para aprender cada uma com calma, comece pela Visão Geral das Coleções.

Nesta página

Todos os exemplos começam com import java.util.*. Na hora de declarar, use a interface à esquerda e a implementação à direita: List<String> nomes = new ArrayList<>();. Assim, trocar de implementação depois é mudar uma palavra.


Qual coleção usar

InterfaceImplementaçãoOrdemDuplicadosnullBuscar / inserirUse quando…
List
sequência com posições
ArrayListde inserção (por índice)simsimget(i) O(1); add no fim O(1)*; inserir/remover no meio O(n); contains O(n)Quase sempre que precisar de uma lista. É a escolha padrão.
LinkedListde inserçãosimsimget(i) O(n); inserir/remover nas pontas O(1)Raramente; para filas e pilhas, prefira ArrayDeque.
Set
sem repetidos
HashSetnenhuma garantidanãoumadd/contains/remove O(1) em médiaSaber rápido "já tem?", eliminar repetidos.
LinkedHashSetde inserçãonãoumO(1) em médiaSem repetidos, mas lembrando a ordem em que entraram.
TreeSetordenada (natural ou Comparator)nãonãoO(log n)Sem repetidos e sempre em ordem; menor, maior, "o próximo depois de x".
Map
chave → valor
HashMapnenhuma garantidachaves não; valores simuma chave, valores simget/put/containsKey O(1) em médiaAchar algo pela chave: dicionário, cadastro por código, contagem.
LinkedHashMapde inserçãochaves nãosimO(1) em médiaComo o HashMap, mas a listagem sai na ordem de inserção.
TreeMapordenada pela chavechaves nãochave não; valores simO(log n)Mapa sempre em ordem de chave; faixas de chaves.
Deque / Queue
pontas
ArrayDequede inserçãosimnãopôr/tirar nas pontas O(1)Pilha (push/pop) ou fila (offer/poll).
PriorityQueuesai sempre o menor (ou o de maior prioridade)simnãooffer/poll O(log n); peek O(1)Processar por prioridade: tarefas urgentes primeiro, menor caminho.

O(1) = tempo constante, não importa o tamanho; O(log n) = cresce muito devagar (1 milhão de itens ≈ 20 passos); O(n) = proporcional ao tamanho (percorre tudo). * Amortizado: de vez em quando o ArrayList precisa crescer e copia tudo, mas na média continua O(1).

Na dúvida

Lista: ArrayList. Sem repetidos: HashSet. Chave → valor: HashMap. Precisa de ordem? Troque por TreeSet/TreeMap (ordenado) ou LinkedHashSet/LinkedHashMap (ordem de inserção). Pilha ou fila: ArrayDeque.

A mesma lista em cada coleção

Cinco frutas, com maçã repetida, copiadas para cada tipo de coleção:

$ jshell
|  Welcome to JShell -- Version 25.0.4.1
|  For an introduction type: /help intro

jshell> import java.util.*

jshell> var frutas = List.of("uva", "maçã", "banana", "kiwi", "maçã")
frutas ==> [uva, maçã, banana, kiwi, maçã]

jshell> new ArrayList<>(frutas)
$3 ==> [uva, maçã, banana, kiwi, maçã]

jshell> new LinkedList<>(frutas)
$4 ==> [uva, maçã, banana, kiwi, maçã]

jshell> new HashSet<>(frutas)
$5 ==> [banana, uva, kiwi, maçã]

jshell> new LinkedHashSet<>(frutas)
$6 ==> [uva, maçã, banana, kiwi]

jshell> new TreeSet<>(frutas)
$7 ==> [banana, kiwi, maçã, uva]

As listas guardam tudo, na ordem. Os conjuntos tiram a maçã repetida: o HashSet numa ordem própria (que pode mudar de uma versão do Java para outra), o LinkedHashSet na ordem de chegada e o TreeSet em ordem alfabética.

Experimente: elimine os repetidos e ordene ao mesmo tempo: crie um TreeSet a partir de List.of(5, 3, 8, 3, 1, 5).

new java.util.TreeSet<>(java.util.List.of(5, 3, 8, 3, 1, 5))

Métodos de List

Valem para ArrayList e LinkedList. Os exemplos rodam em sequência, começando com var l = new ArrayList<>(List.of("Ana", "Bia", "Caio")); cada linha parte do resultado da anterior.

MétodoO que fazExemploResultado
boolean add(E e)Põe no fim.l.add("Duda")true
void add(int i, E e)Põe na posição i, empurrando os outros.l.add(1, "Beto")l = [Ana, Beto, Bia, Caio, Duda]
E get(int i)O item da posição.l.get(0)"Ana"
E set(int i, E e)Troca o item da posição; devolve o antigo.l.set(0, "Aline")"Ana"
int indexOf(Object o)Posição da primeira ocorrência, ou -1.l.indexOf("Caio")3
boolean contains(Object o)Tem esse item? (usa equals)l.contains("Bia")true
boolean remove(Object o)Remove a primeira ocorrência do item.l.remove("Beto")true
E remove(int i)Remove a posição; devolve o removido.l.remove(0)"Aline"
int size()Quantos itens.l.size()3 ([Bia, Caio, Duda])
boolean isEmpty()Está vazia?l.isEmpty()false
List<E> subList(int de, int até)Um pedaço [de, até) (uma "janela" para a lista original).l.subList(0, 2)[Bia, Caio]
void sort(Comparator c)Ordena a própria lista.l.sort(Comparator.reverseOrder())l = [Duda, Caio, Bia]
boolean removeIf(Predicate p)Remove todos que cumprem a condição (lambda).l.removeIf(n -> n.startsWith("C"))true; l = [Duda, Bia]
boolean addAll(Collection c)Põe todos os itens de outra coleção no fim.l.addAll(List.of("Eva", "Fábio"))true; l = [Duda, Bia, Eva, Fábio]
void clear()Esvazia.l.clear(); l.size()0
Collections.sort(lista)Ordena em ordem natural (forma antiga de l.sort(null)). Veja A Classe Collections.Collections.sort(l)[Bia, Caio, Duda]
remove(1) numa List<Integer>

Remove a posição 1, não o número 1. Para remover o valor, escreva lista.remove(Integer.valueOf(1)). Veja ArrayList.


Métodos de Set

Começando com var s = new HashSet<>(Set.of(1, 2, 3)):

MétodoO que fazExemploResultado
boolean add(E e)Põe o item; devolve false se já existia (e não faz nada).s.add(2)
s.add(4)
false
true
boolean contains(Object o)Tem? (rápido: O(1) no HashSet)s.contains(3)true
boolean remove(Object o)Tira o item.s.remove(1)true
int size()Quantos itens.s.size()3
addAll(c)União: junta os itens de outra coleção.{1, 2} .addAll(Set.of(2, 3))[1, 2, 3]
retainAll(c)Interseção: fica só com o que também está na outra.{1, 2, 3, 4, 5} .retainAll(Set.of(2, 4, 6))[2, 4]
removeAll(c)Diferença: tira o que está na outra.{1, 2, 3} .removeAll(Set.of(2))[1, 3]

Só no TreeSet (ordenado), com var t = new TreeSet<>(Set.of(10, 5, 20, 15)):

MétodoO que fazExemploResultado
E first() / E last()O menor / o maior.t.first()
t.last()
5
20
E ceiling(E e)O menor que seja ≥ e (floor: o maior ≤ e).t.ceiling(12)15
SortedSet headSet(E até)Os menores que até (tailSet: os ≥).t.headSet(15)[5, 10]

Métodos de Map

Começando com var m = new HashMap<String, Integer>() (nome → nota):

MétodoO que fazExemploResultado
V put(K chave, V valor)Guarda. Se a chave já existia, substitui e devolve o valor antigo; senão devolve null.m.put("Ana", 8)
m.put("Bia", 9)
m.put("Ana", 10)
null
null
8
V get(Object chave)O valor da chave, ou null se não existe.m.get("Ana")
m.get("Zé")
10
null
V getOrDefault(chave, padrão)Como get, mas com um valor padrão no lugar de null.m.getOrDefault("Zé", 0)0
boolean containsKey(chave)Essa chave existe? (rápido)m.containsKey("Bia")true
boolean containsValue(valor)Algum valor é igual? (percorre tudo: O(n))m.containsValue(9)true
V putIfAbsent(chave, valor)Só guarda se a chave não existir; devolve o valor atual.m.putIfAbsent("Bia", 0)9 (não mudou)
V merge(chave, valor, função)Se a chave não existe, guarda o valor; se existe, junta com a função. O jeito curto de contar.m.merge("Caio", 1, Integer::sum)
(de novo)
1
2
V remove(chave)Tira a chave; devolve o valor que estava.m.remove("Bia")9
Set<K> keySet()As chaves.m.keySet()[Ana, Caio]
Collection<V> values()Os valores.m.values()[10, 2]
Set<Map.Entry<K,V>> entrySet()Os pares chave=valor, para percorrer com for (var e : m.entrySet()) e usar e.getKey()/e.getValue().new TreeMap<>(m).entrySet()[Ana=10, Caio=2]
int size()Quantos pares.m.size()2
new TreeMap<>(mapa)Uma cópia ordenada pela chave (para mostrar em ordem).new TreeMap<>(m){Ana=10, Caio=2}

Só no TreeMap, com var tm = new TreeMap<>(Map.of("c", 3, "a", 1, "b", 2)): tm.firstKey() → "a"; tm.headMap("c") → {a=1, b=2} (as chaves menores que "c"). Também existem lastKey, tailMap, ceilingKey e floorKey.

Missão: conte quantas vezes cada fruta aparece usando um TreeMap<String, Integer> e merge(fruta, 1, Integer::sum). O resultado deve ser {banana=1, kiwi=1, maçã=2, uva=1}.

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        List<String> frutas = List.of("uva", "maçã", "banana", "kiwi", "maçã");
        Map<String, Integer> contagem = new TreeMap<>();
        // conte cada fruta aqui
        System.out.println(contagem);
    }
}
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        List<String> frutas = List.of("uva", "maçã", "banana", "kiwi", "maçã");
        Map<String, Integer> contagem = new TreeMap<>();
        for (String fruta : frutas) {
            contagem.merge(fruta, 1, Integer::sum);
        }
        System.out.println(contagem);
    }
}

Métodos de Deque (pilha e fila)

Deque (double-ended queue, "fila de duas pontas") põe e tira itens nas duas pontas. Com var d = new ArrayDeque<String>():

UsoMétodoO que fazExemploResultado
Pilha
(o último a entrar sai primeiro)
void push(E e)Empilha no topo (a frente).d.push("prato 1")
d.push("prato 2")
d = [prato 2, prato 1]
E peek()Olha o topo sem tirar (null se vazia).d.peek()"prato 2"
E pop()Tira do topo. Vazia: NoSuchElementException.d.pop()"prato 2"
Fila
(o primeiro a entrar sai primeiro)
boolean offerLast(E e) / offerEntra no fim da fila.d.offerLast("fila 1")true
boolean offerFirst(E e)Entra na frente (fura a fila).d.offerFirst("frente")d = [frente, prato 1, fila 1]
E pollFirst() / pollTira da frente. Vazia: null.d.pollFirst()
new ArrayDeque<String>().poll()
"frente"
null
FimE pollLast()Tira do fim.d.pollLast()"fila 1"; d = [prato 1]
PrioridadePriorityQueue.poll()Sai sempre o menor, não importa a ordem de entrada.new PriorityQueue<>(List.of(5, 1, 4, 2)), poll() duas vezes1, depois 2
Pares de métodos: exceção ou valor especial

Cada operação de fila existe em duas versões: uma lança exceção quando não dá (add, remove, element, pop) e outra devolve false/null (offer, poll, peek). Para filas que podem ficar vazias, prefira a segunda e confira o null.


Coleções imutáveis

List.of(…), Set.of(…) e Map.of(…) Java 9+ criam coleções prontas que não podem ser alteradas. Ótimas para dados fixos; para uma lista que vai mudar, copie: new ArrayList<>(List.of(…)). stream().toList() Java 16+ também devolve uma lista imutável.

FormaPode mudar?Aceita null?
new ArrayList<>(), new HashMap<>()…simsim (exceto Tree… e ArrayDeque)
List.of, Set.of, Map.of, stream().toList()nãonão
Arrays.asList(array)pode trocar itens (set), não pode mudar o tamanhosim
Collections.unmodifiableList(l)não (mas é uma "janela" para l: se l mudar, ela muda)sim

Quando dá errado

As mensagens reais, no JShell:

CódigoExceçãoPor quê
List.of(1, 2).add(3)UnsupportedOperationExceptionColeção imutável.
List.of("a", null)NullPointerExceptionList.of não aceita null.
Map.of("a", 1, "a", 2)IllegalArgumentException: duplicate key: aChave repetida em Map.of.
new TreeSet<String>().add(null)NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "k1" is nullO TreeSet/TreeMap precisa comparar, e null não se compara.
new ArrayDeque<String>().add(null)NullPointerExceptionArrayDeque usa null internamente para "vazio".
new ArrayDeque<String>().pop()NoSuchElementExceptionPilha vazia (use poll para receber null).
lista.get(5) com 3 itensIndexOutOfBoundsException: Index 5 out of bounds for length 3Posição inexistente.
Remover dentro de um for-eachConcurrentModificationExceptionA lista mudou durante o laço; use removeIf ou um Iterator.
$ jshell
|  Welcome to JShell -- Version 25.0.4.1
|  For an introduction type: /help intro

jshell> List.of(1, 2).add(3)
|  Exception java.lang.UnsupportedOperationException
|        at ImmutableCollections.uoe (ImmutableCollections.java:159)
|        at ImmutableCollections$AbstractImmutableCollection.add (ImmutableCollections.java:164)
|        at (#1:1)

jshell> Map.of("a", 1, "a", 2)
|  Exception java.lang.IllegalArgumentException: duplicate key: a
|        at ImmutableCollections$MapN.<init> (ImmutableCollections.java:1440)
|        at Map.of (Map.java:1384)
|        at (#2:1)

Mais detalhes sobre cada exceção em Exceções Comuns.


Exercícios

1. Você precisa guardar os e-mails já cadastrados e perguntar muitas vezes "este já existe?". Qual coleção?

2. O que m.put("Ana", 10) devolve se "Ana" já valia 8?

3. Qual destas coleções aceita null?

Complete para criar um mapa que lista as chaves em ordem alfabética:

Map<String, Integer> notas = new ;

Resumo

  • List = sequência com posições e repetidos; Set = sem repetidos; Map = chave → valor; Deque = pilha e fila.
  • Hash…: rápido, sem ordem; Linked…: ordem de inserção; Tree…: ordenado, O(log n), sem null.
  • Padrões: ArrayList, HashSet, HashMap, ArrayDeque. Declare pela interface.
  • List.of/Set.of/Map.of são imutáveis e recusam null.