Guia para o Apache Commons MultiValuedMap
1. Visão geral
Neste tutorial rápido, daremos uma olhada na interfaceMultiValuedMap fornecida na biblioteca Apache Commons Collections.
MultiValuedMap provides a simple API for mapping each key to a collection of values in Java. é o sucessor deorg.apache.commons.collections4.MultiMap, que foi descontinuado no Commons Collection 4.1.
2. Dependência do Maven
Para projetos Maven, precisamos adicionar a dependênciacommons-collections4:
org.apache.commons
commons-collections4
4.2
3. Adicionando elementos em umMultiValuedMap
Podemos adicionar elementos usando os métodosputeputAll.
Vamos começar criando uma instância deMultiValuedMap:
MultiValuedMap map = new ArrayListValuedHashMap<>();
A seguir, vamos ver como podemos adicionar elementos um de cada vez usando o métodoput:
map.put("fruits", "apple");
map.put("fruits", "orange");
Além disso, vamos adicionar alguns elementos usando o métodoputAll, que mapeia uma chave para vários elementos em uma única chamada:
map.putAll("vehicles", Arrays.asList("car", "bike"));
assertThat((Collection) map.get("vehicles"))
.containsExactly("car", "bike");
4. Recuperando Elementos de umMultiValuedMap
MultiValuedMap fornece métodos para recuperar chaves, valores e mapeamentos de valores-chave. Vamos dar uma olhada em cada um deles.
4.1. Obter todos os valores de uma chave
Para obter todos os valores associados a uma chave, podemos usar o métodoget , que retorna umCollection:
assertThat((Collection) map.get("fruits"))
.containsExactly("apple", "orange");
4.2. Obter todos os mapeamentos de valores-chave
Ou podemos usar o métodoentries para obterCollection de todos os mapeamentos de valores-chave contidos no mapa:
Collection> entries = map.entries();
4.3. Obter todas as chaves
Existem dois métodos para recuperar todas as chaves contidas em umMultiValuedMap.
Vamos usar o métodokeys para obter uma visualizaçãoMultiSet das chaves:
MultiSet keys = map.keys();
assertThat(keys).contains("fruits", "vehicles");
Como alternativa, podemos obter uma visualizaçãoSet das chaves usando o métodokeySet :
Set keys = map.keySet();
assertThat(keys).contains("fruits", "vehicles");
4.4. Obter todos os valores de um mapa
Finalmente, se quisermos obter uma visualizaçãoCollection de todos os valores contidos no mapa, podemos usar o métodovalues :
Collection values = map.values();
assertThat(values).contains("apple", "orange", "car", "bike");
5. Removendo Elementos de umMultiValuedMap
Agora, vamos examinar todos os métodos para remover elementos e mapeamentos de valores-chave.
5.1. Remover todos os elementos mapeados para uma chave
Primeiro, vamos ver como remover todos os valores associados a uma chave especificada usando o método remove :
Collection removedValues = map.remove("fruits");
assertThat(map.containsKey("fruits")).isFalse();
assertThat(removedValues).contains("apple", "orange");
Este método retorna uma visualizaçãoCollection dos valores removidos.
5.2. Remover um mapeamento de valor-chave único
Agora, suponha que tenhamos uma chave mapeada para vários valores, mas queremos remover apenas um dos valores mapeados, deixando os outros. Podemos fazer isso facilmente usando o métodoremoveMapping :
boolean isRemoved = map.removeMapping("fruits","apple");
assertThat(map.containsMapping("fruits","apple")).isFalse();
5.3. Remover todos os mapeamentos de valores-chave
E, finalmente, podemos usar o métodoclear para remover todos os mapeamentos do mapa:
map.clear();
assertThat(map.isEmpty()).isTrue();
6. Verificando elementos de umMultiValuedMap
A seguir, vamos dar uma olhada nos vários métodos para verificar se uma chave ou valor especificado existe em nosso mapa.
6.1. Verifique se existe uma chave
Para descobrir se nosso mapa contém um mapeamento para uma chave especificada, podemos usar o métodocontainsKey:
assertThat(map.containsKey("vehicles")).isTrue();
6.2. Verifique se existe um valor
Em seguida, suponha que desejamos verificar se pelo menos uma chave em nosso mapa contém um mapeamento para um valor específico. Podemos fazer isso usando o métodocontainsValue:
assertThat(map.containsValue("orange")).isTrue();
6.3. Verificar se existe um mapeamento de valor-chave
Da mesma forma, se quisermos verificar se um mapa contém um mapeamento para um par de chave e valor específico, podemos usar o métodocontainsMapping:
assertThat(map.containsMapping("fruits","orange")).isTrue();
6.4. Verifique se um mapa está vazio
Para verificar se um mapa não contém nenhum mapeamento de valor-chave, podemos usar o métodoisEmpty:
assertThat(map.isEmpty()).isFalse;
6.5. Verifique o tamanho de um mapa
Finalmente, podemos usar o métodosize para obter o tamanho total do mapa. Quando um mapa possui chaves com vários valores, o tamanho total do mapa é a contagem de todos os valores de todas as chaves:
assertEquals(4, map.size());
7. Implementações
A Biblioteca de Coleções Apache Commons também fornece várias implementações dessa interface. Vamos dar uma olhada neles.
7.1. ArrayListValuedHashMap
UmArrayListValuedHashMap usa umArrayList internamente para armazenar os valores associados a cada chave, entãoit allows duplicate key-values pairs:
MultiValuedMap map = new ArrayListValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "orange");
map.put("fruits", "orange");
assertThat((Collection) map.get("fruits"))
.containsExactly("apple", "orange", "orange");
Agora, é importante notar que esteclass is not thread-safe. Portanto, se quisermos usar este mapa a partir de vários threads, devemos ter certeza de usar a sincronização adequada.
7.2. HashSetValuedHashMap
AHashSetValuedHashMap usaHashSet para armazenar os valores de cada chave fornecida. Portanto,it doesn’t allow duplicate key-value pairs.
Vejamos um exemplo rápido, onde adicionamos o mesmo mapeamento de valor-chave duas vezes:
MultiValuedMap map = new HashSetValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "apple");
assertThat((Collection) map.get("fruits"))
.containsExactly("apple");
Observe como, ao contrário de nosso exemplo anterior que usouArrayListValuedHashMap,, a implementação deHashSetValuedHashMap ignora o mapeamento duplicado.
OHashSetValuedHashMapclass is also not thread-safe.
7.3. UnmodifiableMultiValuedMap
OUnmodifiableMultiValuedMap é uma classe de decorador útil quando precisamos de uma instância imutável deMultiValuedMap - ou seja, não deve permitir modificações adicionais:
@Test(expected = UnsupportedOperationException.class)
public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() {
MultiValuedMap map = new ArrayListValuedHashMap<>();
map.put("fruits", "apple");
map.put("fruits", "orange");
MultiValuedMap immutableMap =
MultiMapUtils.unmodifiableMultiValuedMap(map);
immutableMap.put("fruits", "banana"); // throws exception
}
E, novamente, é importante notar que modificarthe final put will result in an UnsupportedOperationException.
8. Conclusão
Vimos vários métodos da interfaceMultiValuedMap da biblioteca Apache Commons Collections. Além disso, exploramos algumas implementações populares.
E, como sempre, o código-fonte completo está disponívelover on Github.