Interface Collection do Java
A interface Collection raiz do Java e o contrato que toda lista, conjunto e fila herda dela.
java.util.Collection<E> é a raiz da parte do framework que armazena elementos individuais — todo List, Set, Queue e Deque a implementa (a única família que não o faz é Map, cujos elementos são entradas, não valores individuais). Tudo o que você pode fazer "independentemente do grupo" — adicionar, remover, verificar contains, iterar, contar, converter para array, fazer stream — é declarado aqui. Este capítulo trata do contrato: os métodos nos quais você pode confiar para qualquer coleção, os poucos que podem lançar exceções e o modelo de iteração que toda implementação herda.
A hierarquia em resumo
Iterable<E>
└── Collection<E>
├── List<E> — ordered, indexed, duplicates allowed
├── Set<E> — no duplicates
│ └── SortedSet<E> → NavigableSet<E>
└── Queue<E> — "next in line"
└── Deque<E> — double-ended queueCollection estende Iterable<E>, e é por isso que toda coleção funciona com o laço for-each. As duas especializações de Collection — Set e Queue — refinam o contrato; Map possui sua própria raiz.
Métodos principais que toda coleção possui
Abaixo está o conjunto completo de métodos de instância em Collection, agrupados por finalidade. Memorize as categorias em vez da lista — assim que souber que existe um método chamado removeIf, você consegue encontrá-lo.
Tamanho e vazio
int size()— contagem de elementos.boolean isEmpty()—size() == 0, mas frequentemente mais rápido.
Adição
boolean add(E e)— adiciona um elemento. Retornatruese a coleção foi alterada. (UmSetretornafalsepara um duplicado.)boolean addAll(Collection<? extends E> c)— adiciona todos os elementos dec.
Remoção
boolean remove(Object o)— remove uma ocorrência deo.boolean removeAll(Collection<?> c)— remove todos os elementos que aparecem emc.boolean retainAll(Collection<?> c)— mantém apenas os elementos emc(interseção).boolean removeIf(Predicate<? super E> filter)— remove todos os elementos que correspondem ao predicado. A forma mais limpa de filtrar no lugar.void clear()— esvazia a coleção.
Consulta
boolean contains(Object o)— teste de pertencimento.boolean containsAll(Collection<?> c)— teste de subconjunto.
Iteração e visões em lote
Iterator<E> iterator()— o iterador subjacente; o que ofor-eachutiliza.Stream<E> stream()/parallelStream()— abre umStreamsobre os elementos.void forEach(Consumer<? super E> action)— herdado deIterable. A forma funcional de iteração.
Conversão para array
Object[] toArray()<T> T[] toArray(T[] a)e o mais recente<T> T[] toArray(IntFunction<T[]> generator)(Java 11+) — array tipado.
Essa é a interface completa. Toda lista, conjunto e fila que você encontrar nesta parte é apenas uma implementação diferente desses métodos mais alguns específicos dela.
Igualdade e equals / hashCode
Collection.equals(Object) não é definido na raiz — cada sub-interface especifica o que a igualdade significa para ela. List requer os mesmos elementos na mesma ordem; Set requer os mesmos elementos independentemente da ordem; Queue não define equals (uma fila LinkedList e uma fila ArrayDeque com o mesmo conteúdo não são iguais, pois a comparação recai sobre a identidade). Não compare coleções de famílias diferentes esperando simetria.
Elementos armazenados em uma Collection devem ter equals / hashCode coerentes se você quiser que contains, remove e (para coleções baseadas em hash) a busca funcionem corretamente. Cobrimos o contrato no capítulo equals e hashCode — esse é o pré-requisito para usar Set e Map com suas próprias classes.
Operações opcionais
Algumas coleções são imutáveis — List.of(1,2,3), Collections.unmodifiableList(list), as visões retornadas de Map.keySet() em certas implementações, etc. Elas ainda implementam Collection, mas chamar add, remove, clear ou qualquer método de mutação lança UnsupportedOperationException. O Javadoc chama essas de "operações opcionais." É o mais próximo que o Java tem de uma recusa em tempo de execução para partes de uma interface; o preço é que o compilador não consegue detectar o erro — você descobre no primeiro lançamento.
Uma regra segura: se você não construiu a coleção, trate-a como possivelmente imutável. Se precisar de uma cópia mutável, faça new ArrayList<>(received) primeiro.
Iteração: três formas, um mecanismo subjacente
Toda coleção suporta três estilos de iteração, e todos os três acabam chamando iterator():
Collection<String> names = List.of("Ada", "Linus", "Grace");
// 1. for-each — the everyday form
for (String n : names) System.out.println(n);
// 2. forEach with a lambda — declarative
names.forEach(System.out::println);
// 3. Iterator — when you need to remove during iteration
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.startsWith("L")) it.remove(); // safe; for-each can't do this
}Por que as formas 1 e 3 ainda importam: o laço for-each não consegue modificar a coleção subjacente sem lançar ConcurrentModificationException. Quando você precisa remover durante a iteração, recorre ao Iterator explícito. O capítulo Iteradores mais adiante nesta parte cobre o protocolo em detalhes.
Álgebra de conjuntos com operações em lote
As operações em lote transformam uma coleção em uma calculadora de álgebra de conjuntos (independentemente de ser um Set — elas funcionam em List também):
Collection<Integer> a = new ArrayList<>(List.of(1, 2, 3, 4));
Collection<Integer> b = List.of(3, 4, 5);
a.addAll(b); // union (multiset)
a.retainAll(List.of(3, 4)); // intersection
a.removeAll(List.of(3)); // differenceEssa é a maneira segura e sem dependências de expressar "manter apenas os itens que também estão em b" sem escrever um laço. Elas modificam o receptor — se você precisar de um resultado imutável, copie primeiro.
Um exemplo completo: todos os métodos, lado a lado
O programa abaixo exercita cada categoria de método de Collection contra o mesmo ArrayList, para que você possa vê-los em um lugar e observar o contrato em ação.
Dois pontos merecem destaque na saída:
remove("red")removeu apenas a primeira ocorrência — esse é o contrato deCollection. Para remover toda correspondência, useremoveIf(você o viu a seguir, removendo cada palavra com mais de quatro caracteres).- O
UnsupportedOperationExceptiondefrozen.add("d")é a regra das "operações opcionais" em ação.frozenimplementaCollection, então a chamada compila. A implementação optou por não suportá-la, e você descobre isso em tempo de execução.
O que vem a seguir
Collection é o contrato abstrato. O primeiro refinamento concreto que você encontrará é aquele que adiciona ordem e indexação — a interface List. É onde o acesso indexado, as sublistas e as operações que preservam a ordem entram em cena.