W3docs

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 queue

Collection estende Iterable<E>, e é por isso que toda coleção funciona com o laço for-each. As duas especializações de CollectionSet 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. Retorna true se a coleção foi alterada. (Um Set retorna false para um duplicado.)
  • boolean addAll(Collection<? extends E> c) — adiciona todos os elementos de c.

Remoção

  • boolean remove(Object o) — remove uma ocorrência de o.
  • boolean removeAll(Collection<?> c) — remove todos os elementos que aparecem em c.
  • boolean retainAll(Collection<?> c) — mantém apenas os elementos em c (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 o for-each utiliza.
  • Stream<E> stream() / parallelStream() — abre um Stream sobre os elementos.
  • void forEach(Consumer<? super E> action) — herdado de Iterable. 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));     // difference

Essa é 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.

java— editable, runs on the server

Dois pontos merecem destaque na saída:

  1. remove("red") removeu apenas a primeira ocorrência — esse é o contrato de Collection. Para remover toda correspondência, use removeIf (você o viu a seguir, removendo cada palavra com mais de quatro caracteres).
  2. O UnsupportedOperationException de frozen.add("d") é a regra das "operações opcionais" em ação. frozen implementa Collection, 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.

Prática

Prática
Você tem uma `Collection<String>` e quer remover todo elemento cujo comprimento seja maior que quatro. Qual abordagem é a forma idiomática em uma única instrução?
Você tem uma `Collection<String>` e quer remover todo elemento cujo comprimento seja maior que quatro. Qual abordagem é a forma idiomática em uma única instrução?
Was this page helpful?