Há alguns casos em que você prefere usar mapas, listas, conjuntos ou outros tipos de coleções imutáveis.
O primeiro e discutível caso de uso mais importante é sempre que você retorna um resultado de uma consulta ou um cálculo que retornaria um conjunto (ou lista ou mapa) de resultados; você deve preferir usar estruturas de dados imutáveis.
Nesse caso, prefiro retornar versões imutáveis delas, pois isso reflete a imutabilidade factual de um conjunto de resultados de uma computação muito mais claramente - não importa o que você faça com os dados posteriormente, o conjunto de resultados que você recebeu da sua consulta não deve mudança.
O segundo caso de uso comum é quando você precisa fornecer um argumento como uma entrada para um método ou serviço. A menos que você espere que a coleção de entrada seja modificada pelo serviço ou método (que geralmente é uma péssima idéia de design), passar uma coleção imutável em vez da mutável pode ser a escolha razoável e segura em muitos casos.
Eu penso nisso como uma convenção de "passar por valor" .
Mais geralmente - é uma prática sensata usar estruturas de dados imutáveis sempre que os dados ultrapassam os limites do módulo ou do serviço. Isso facilita muito o raciocínio sobre as diferenças entre entrada / saída (imutável) e estado interno mutável.
Como um efeito colateral muito benéfico, isso aumenta a segurança e a segurança dos threads de seus módulos / serviços e garante uma separação mais limpa das preocupações.
Outra boa razão para usar Collections.empty*()
métodos é a notável falta de detalhamento. Na era pré-Java7, se você tinha uma coleção genérica, precisava espalhar anotações de tipo genérico por todo o lado.
Basta comparar estas duas declarações:
Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();
versus:
Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();
O último ganha claramente a legibilidade de duas maneiras importantes:
- Na primeira declaração, toda a instanciação de um mapa vazio é escondida no ruído das declarações de tipo genéricas, tornando uma declaração essencialmente trivial muito mais enigmática do que precisa ser.
- Além da notável falta de anotação de tipo genérico no lado direito, a segunda versão indica claramente que o mapa é inicializado em um mapa vazio. Além disso - sabendo que esse método retorna um mapa imutável, agora é mais fácil descobrir onde
fooBarMap
está sendo atribuído outro valor não vazio apenas pesquisando /fooBarMap =/
.