This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git
The following commit(s) were added to refs/heads/master by this push:
new 54dded70b [COLLECTIONS-881] MultiMapUtils.getXXX ensure safe copy
(#669)
54dded70b is described below
commit 54dded70be00b36586f5846941bf65d352da6949
Author: Suhyeon Park <[email protected]>
AuthorDate: Mon Jun 15 06:00:39 2026 +0900
[COLLECTIONS-881] MultiMapUtils.getXXX ensure safe copy (#669)
---
.../apache/commons/collections4/MultiMapUtils.java | 18 ++------
.../commons/collections4/MultiMapUtilsTest.java | 48 +++++++++++++++++++++-
2 files changed, 50 insertions(+), 16 deletions(-)
diff --git a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
index 226f1dc52..11806413d 100644
--- a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
+++ b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java
@@ -102,14 +102,11 @@ public class MultiMapUtils {
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
- * @return the Collection in the {@link MultiValuedMap} as Bag, or null if
input map is null
+ * @return a new Bag containing the values from the {@link
MultiValuedMap}, or null if input map is null
*/
public static <K, V> Bag<V> getValuesAsBag(final MultiValuedMap<K, V> map,
final K key) {
if (map != null) {
final Collection<V> col = map.get(key);
- if (col instanceof Bag) {
- return (Bag<V>) col;
- }
return new HashBag<>(col);
}
return null;
@@ -122,22 +119,16 @@ public class MultiMapUtils {
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
- * @return the Collection in the {@link MultiValuedMap} as List, or null
if input map is null
+ * @return a new List containing the values from the {@link
MultiValuedMap}, or null if input map is null
*/
public static <K, V> List<V> getValuesAsList(final MultiValuedMap<K, V>
map, final K key) {
if (map != null) {
final Collection<V> col = map.get(key);
- if (col instanceof List) {
- return (List<V>) col;
- }
return new ArrayList<>(col);
}
return null;
}
- // TODO: review the getValuesAsXXX methods - depending on the actual
MultiValuedMap type, changes
- // to the returned collection might update the backing map. This should be
clarified and/or prevented.
-
/**
* Gets a Set from {@code MultiValuedMap} in a null-safe manner.
*
@@ -145,14 +136,11 @@ public class MultiMapUtils {
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
- * @return the Collection in the {@link MultiValuedMap} as Set, or null if
input map is null
+ * @return a new Set containing the values from the {@link
MultiValuedMap}, or null if input map is null
*/
public static <K, V> Set<V> getValuesAsSet(final MultiValuedMap<K, V> map,
final K key) {
if (map != null) {
final Collection<V> col = map.get(key);
- if (col instanceof Set) {
- return (Set<V>) col;
- }
return new HashSet<>(col);
}
return null;
diff --git
a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
index 7ff98ba07..4bb3528d0 100644
--- a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
+++ b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java
@@ -16,6 +16,10 @@
*/
package org.apache.commons.collections4;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.easymock.EasyMock.createMock;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -28,6 +32,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import
org.apache.commons.collections4.multimap.LinkedHashSetValuedLinkedHashMap;
@@ -105,7 +110,7 @@ class MultiMapUtilsTest {
@Test
void testGetValuesAsSet() {
- assertNull(MultiMapUtils.getValuesAsList(null, "key1"));
+ assertNull(MultiMapUtils.getValuesAsSet(null, "key1"));
final String[] values = { "v1", "v2", "v3" };
final MultiValuedMap<String, String> map = new
ArrayListValuedHashMap<>();
@@ -118,6 +123,47 @@ class MultiMapUtilsTest {
assertEquals(new HashSet<>(Arrays.asList(values)), set);
}
+ @Test
+ void testGetValuesAsBagIsSafeCopy() {
+ final String[] values = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> mockMap =
createMock(MultiValuedMap.class);
+ final Bag<String> bagToReturn = new HashBag<>();
+ bagToReturn.addAll(Arrays.asList(values));
+ expect(mockMap.get("key1")).andReturn(bagToReturn);
+ replay(mockMap);
+
+ final Bag<String> bag = MultiMapUtils.getValuesAsBag(mockMap, "key1");
+ bag.add("v4");
+ assertFalse(bagToReturn.contains("v4"));
+ verify(mockMap);
+ }
+
+ @Test
+ void testGetValuesAsListIsSafeCopy() {
+ final String[] values = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new
ArrayListValuedHashMap<>();
+ for (final String val : values) {
+ map.put("key1", val);
+ }
+
+ final List<String> list = MultiMapUtils.getValuesAsList(map, "key1");
+ list.add("v4");
+ assertFalse(map.containsMapping("key1", "v4"));
+ }
+
+ @Test
+ void testGetValuesAsSetIsSafeCopy() {
+ final String[] values = { "v1", "v2", "v3" };
+ final MultiValuedMap<String, String> map = new
HashSetValuedHashMap<>();
+ for (final String val : values) {
+ map.put("key1", val);
+ }
+
+ final Set<String> set = MultiMapUtils.getValuesAsSet(map, "key1");
+ set.add("v4");
+ assertFalse(map.containsMapping("key1", "v4"));
+ }
+
@Test
void testInvert() {
final HashSetValuedHashMap<String, String> usages = new
HashSetValuedHashMap<>();