Anleitung zu Apache Commons MultiValuedMap

1. Übersicht

In diesem kurzen Tutorial sehen wir uns die MultiValuedMap- Oberfläche an, die in der Apache Commons Collections-Bibliothek bereitgestellt wird .

MultiValuedMap bietet eine einfache API zum Zuordnen jedes Schlüssels zu einer Sammlung von Werten in Java. Es ist der Nachfolger von org.apache.commons.collections4.MultiMap, der in Commons Collection 4.1 veraltet war.

2. Maven-Abhängigkeit

Für Maven-Projekte müssen wir die Abhängigkeit commons-collection4 hinzufügen :

 org.apache.commons commons-collections4 4.2 

3. Hinzufügen von Elementen zu einer MultiValuedMap

Wir können Elemente mit den Methoden put und putAll hinzufügen .

Beginnen wir mit der Erstellung einer Instanz von MultiValuedMap :

MultiValuedMap map = new ArrayListValuedHashMap();

Als nächstes wollen wir sehen, wie wir mit der put- Methode nacheinander Elemente hinzufügen können :

map.put("fruits", "apple"); map.put("fruits", "orange");

Fügen Sie außerdem einige Elemente mithilfe der putAll- Methode hinzu, mit der ein Schlüssel mehreren Elementen in einem einzigen Aufruf zugeordnet wird:

map.putAll("vehicles", Arrays.asList("car", "bike")); assertThat((Collection) map.get("vehicles")) .containsExactly("car", "bike");

4. Abrufen von Elementen aus einer MultiValuedMap

MultiValuedMap bietet Methoden zum Abrufen von Schlüsseln, Werten und Schlüsselwertzuordnungen. Schauen wir uns diese an.

4.1. Holen Sie sich alle Werte eines Schlüssels

Um alle mit einem Schlüssel verknüpften Werte abzurufen, können Sie die get- Methode verwenden, die eine Collection zurückgibt :

assertThat((Collection) map.get("fruits")) .containsExactly("apple", "orange");

4.2. Holen Sie sich alle Schlüsselwertzuordnungen

Oder wir können die Eingabemethode verwenden, um eine Sammlung aller in der Karte enthaltenen Schlüsselwertzuordnungen abzurufen:

Collection
    
      entries = map.entries();
    

4.3. Holen Sie sich alle Schlüssel

Es gibt zwei Methoden zum Abrufen aller in einer MultiValuedMap enthaltenen Schlüssel .

Verwenden Sie die Schlüsselmethode , um eine MultiSet- Ansicht der Schlüssel zu erhalten:

MultiSet keys = map.keys(); assertThat(keys).contains("fruits", "vehicles");

Alternativ können wir mit der keySet- Methode eine Set- Ansicht der Schlüssel erhalten :

Set keys = map.keySet(); assertThat(keys).contains("fruits", "vehicles");

4.4. Holen Sie sich alle Werte einer Karte

Wenn wir eine Sammlungsansicht aller in der Karte enthaltenen Werte erhalten möchten , können wir die Methode values verwenden:

Collection values = map.values(); assertThat(values).contains("apple", "orange", "car", "bike");

5. Entfernen von Elementen aus einer MultiValuedMap

Schauen wir uns nun alle Methoden zum Entfernen von Elementen und Schlüsselwertzuordnungen an.

5.1. Entfernen Sie alle einem Schlüssel zugeordneten Elemente

Lassen Sie uns zunächst sehen, wie Sie alle mit einem angegebenen Schlüssel verknüpften Werte mithilfe der Methode remove entfernen :

Collection removedValues = map.remove("fruits"); assertThat(map.containsKey("fruits")).isFalse(); assertThat(removedValues).contains("apple", "orange");

Diese Methode gibt eine Sammlungsansicht der entfernten Werte zurück.

5.2. Entfernen Sie eine einzelne Schlüsselwertzuordnung

Angenommen, wir haben einen Schlüssel, der mehreren Werten zugeordnet ist, aber wir möchten nur einen der zugeordneten Werte entfernen und die anderen belassen. Wir können dies einfach mit der removeMapping- Methode tun :

boolean isRemoved = map.removeMapping("fruits","apple"); assertThat(map.containsMapping("fruits","apple")).isFalse();

5.3. Entfernen Sie alle Schlüsselwertzuordnungen

Und schließlich können wir die Clear- Methode verwenden, um alle Zuordnungen von der Karte zu entfernen:

map.clear(); assertThat(map.isEmpty()).isTrue();

6. Überprüfen von Elementen aus einer MultiValuedMap

Next, let's take a look at the various methods for checking whether a specified key or value exists in our map.

6.1. Check If a Key Exists

To find out whether our map contains a mapping for a specified key, we can use the containsKey method:

assertThat(map.containsKey("vehicles")).isTrue();

6.2. Check If a Value Exists

Next, suppose we want to check if at least one key in our map contains a mapping for a particular value. We can do this using the containsValue method:

assertThat(map.containsValue("orange")).isTrue();

6.3. Check If a Key-Value Mapping Exists

Similarly, if we want to check whether a map contains a mapping for a specific key and value pair, we can use the containsMapping method:

assertThat(map.containsMapping("fruits","orange")).isTrue();

6.4. Check If a Map Is Empty

To check if a map does not contain any key-value mappings at all, we can use the isEmpty method:

assertThat(map.isEmpty()).isFalse;

6.5. Check the Size of a Map

Finally, we can use the size method to get the total size of the map. When a map has keys with multiple values, then the total size of the map is the count of all the values from all keys:

assertEquals(4, map.size());

7. Implementations

The Apache Commons Collections Library also provides multiple implementations of this interface. Let's have a look at them.

7.1. ArrayListValuedHashMap

An ArrayListValuedHashMap uses an ArrayList internally for storing the values associated with each key, so it 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");

Now, it's worth noting that this class is not thread-safe. Therefore, if we want to use this map from multiple threads, we must be sure to use proper synchronization.

7.2. HashSetValuedHashMap

A HashSetValuedHashMap uses a HashSet for storing the values for each given key. Therefore, it doesn't allow duplicate key-value pairs.

Let's see a quick example, where we add the same key-value mapping twice:

MultiValuedMap map = new HashSetValuedHashMap(); map.put("fruits", "apple"); map.put("fruits", "apple"); assertThat((Collection) map.get("fruits")) .containsExactly("apple");

Notice how, unlike our previous example that used ArrayListValuedHashMap, the HashSetValuedHashMap implementation ignores the duplicate mapping.

The HashSetValuedHashMapclass is also not thread-safe.

7.3. UnmodifizierbareMultiValuedMap

Die UnmodutableMultiValuedMap ist eine Dekorationsklasse, die nützlich ist, wenn wir eine unveränderliche Instanz einer MultiValuedMap benötigen - das heißt, sie sollte keine weiteren Änderungen zulassen:

@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 }

Und wieder ist es erwähnenswert, dass das Ändern des endgültigen Put zu einer UnsupportedOperationException führt .

8. Fazit

Wir haben verschiedene Methoden der MultiValuedMap- Schnittstelle aus der Apache Commons Collections-Bibliothek gesehen. Darüber hinaus haben wir einige beliebte Implementierungen untersucht.

Und wie immer ist der vollständige Quellcode auf Github verfügbar.