Coleções e Tipos Genéricos¶
O Java Collections Framework separa interfaces como List, Set,
Queue e Map de implementações com diferentes propriedades de desempenho e ordenação.
Programar para o contrato necessário¶
static List<String> normalizedNames(Collection<String> names) {
List<String> result = new ArrayList<>(names.size());
for (String name : names) {
result.add(name.strip().toLowerCase(Locale.ROOT));
}
return List.copyOf(result);
}
O parâmetro requer apenas iteração e tamanho, enquanto o contrato de retorno é uma lista imutável. "Imutável" não torna elementos mutáveis referenciados profundamente imutáveis.
Tipos genéricos¶
Tipos genéricos fornecem segurança de tipos em tempo de compilação. Os tipos genéricos de Java são invariantes:
List<Integer> não é um subtipo de List<Number>. Wildcards expressam variação
em um limite de API.
static double sum(List<? extends Number> values) {
double total = 0;
for (Number value : values) total += value.doubleValue();
return total;
}
static void addDefaults(List<? super Integer> destination) {
destination.add(0);
destination.add(1);
}
O mnemônico PECS significa produtor-extends, consumidor-super. Um valor lido
de ? super Integer é apenas conhecido como Object; um Number arbitrário não-nulo
não pode ser adicionado com segurança a ? extends Number.
Guia de seleção¶
| Necessidade | Implementação típica |
|---|---|
| Sequência indexada | ArrayList |
| Valores únicos, sem requisito de ordem de iteração | HashSet |
| Conjunto/mapa ordenado por inserção | LinkedHashSet / LinkedHashMap |
| Chaves ordenadas | TreeSet / TreeMap |
| Pilha ou fila | ArrayDeque |
| Acesso de prioridade | PriorityQueue |
Erros comuns¶
- modificar uma coleção durante um laço for-each fora do contrato do iterador;
- usar objetos mutáveis como chaves hash;
- presumir ordem de iteração de
HashMap; - retornar diretamente uma coleção interna mutável;
- selecionar uma coleção concorrente sem entender suas operações atômicas.