From 4079f86872d81dcdf29512dad0d507babc91f554 Mon Sep 17 00:00:00 2001 From: Suhyeon Park Date: Thu, 25 Dec 2025 17:30:17 +0900 Subject: [PATCH] [COLLECTIONS-880] Add MultiMapUtils.invert(Map, MultiValuedMap) overload --- .../commons/collections4/MultiMapUtils.java | 20 +++++++++++++ .../collections4/MultiMapUtilsTest.java | 28 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java index 82bebab7c8..a86e1aa233 100644 --- a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java +++ b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java @@ -179,6 +179,26 @@ M invert(MultiValuedMap input, M output) { return output; } + /** + * A utility method to invert the mappings from an input Map + * and add them to an output MultiValuedMap. Use this method to have complete + * control of the output MultiValuedMap or when merging several inverse mappings. + * + * @param input take key-to-value mappings from here + * @param output add value-to-key mappings here + * @param the output MultiValuedMap key type and the input Map value type + * @param the output MultiValuedMap value type and the input Map key type + * @param the output MultiValuedMap with key and value types reversed compared with input + * @return the updated output MultiValuedMap + */ + public static > + M invert(Map input, M output) { + for (Map.Entry e : input.entrySet()) { + output.put(e.getValue(), e.getKey()); + } + return output; + } + /** * Null-safe check if the specified {@code MultiValuedMap} is empty. *

diff --git a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java index 7ff98ba078..bfa8e302da 100644 --- a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java @@ -24,8 +24,10 @@ import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; @@ -119,7 +121,7 @@ void testGetValuesAsSet() { } @Test - void testInvert() { + void testInvertMultiValuedMap() { final HashSetValuedHashMap usages = new HashSetValuedHashMap<>(); final LinkedHashSetValuedLinkedHashMap deps = new LinkedHashSetValuedLinkedHashMap<>(); @@ -142,6 +144,30 @@ void testInvert() { assertEquals("[commons-collections, commons-configuration2]", codecUsagesAll.toString()); } + @Test + void testInvertMap() { + final HashSetValuedHashMap usages = new HashSetValuedHashMap<>(); + + final Map deps = new HashMap<>(); + deps.put("commons-configuration1", "commons-logging"); + deps.put("commons-configuration2", "commons-lang3"); + deps.put("commons-configuration3", "commons-text"); + deps.put("commons-beanutils1", "commons-collections"); + deps.put("commons-beanutils2", "commons-logging"); + MultiMapUtils.invert(deps, usages); + final Set loggingUsagesCompile = usages.get("commons-logging"); + assertEquals("[commons-beanutils2, commons-configuration1]", loggingUsagesCompile.toString()); + final Set codecUsagesCompile = usages.get("commons-codec"); + assertEquals("[]", codecUsagesCompile.toString()); + + final Map optionalDeps = new HashMap<>(); + optionalDeps.put("commons-configuration2", "commons-codec"); + optionalDeps.put("commons-collections", "commons-codec"); + MultiMapUtils.invert(optionalDeps, usages); + final Set codecUsagesAll = usages.get("commons-codec"); + assertEquals("[commons-collections, commons-configuration2]", codecUsagesAll.toString()); + } + @Test void testIsEmptyWithEmptyMap() { assertTrue(MultiMapUtils.isEmpty(new ArrayListValuedHashMap<>()));