Guia para o Apache Commons MultiValuedMap

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.MultiMapque 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.