From b7ebe448665c61eed3d3acbb7c4477b2b452bfed Mon Sep 17 00:00:00 2001 From: Sharang Gupta Date: Wed, 14 Oct 2026 08:36:03 +0100 Subject: [PATCH] [COLLECTIONS-732] Document that MultiValuedMap.mapIterator() does not support setValue() The iterator returned by mapIterator() iterates read-only MultiValuedMapEntry instances, so MapIterator.setValue(Object) always throws UnsupportedOperationException, but neither the interface nor the implementation said so. Say it in the Javadoc of MultiValuedMap.mapIterator(), of the AbstractMultiValuedMap override and of the iterator's setValue(), and point to remove() plus put() as the way to replace a value. No code change; the behaviour is already pinned by AbstractMultiValuedMapTest.testMapIteratorUnsupportedSet(). --- src/changes/changes.xml | 1 + .../commons/collections4/MultiValuedMap.java | 5 +++++ .../multimap/AbstractMultiValuedMap.java | 15 +++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fc6a80359d..2f09a3654c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -29,6 +29,7 @@ Update the index on remove via IndexedCollection.iterator() (#724). [Javadoc] Fix grammar in ArrayStack class Javadoc (#725). General Javadoc improvements. + [Javadoc] Document that MultiValuedMap.mapIterator() does not support MapIterator.setValue(Object). Fix AbstractLinkedList addAll returning true for an empty collection (#726). AbstractSetTest cannot be used with an explicitly typed Set (unless it's based on String) (#727). Fix map and bidimap nextKey() skipping a key and throwing for keys not in the map (#728). diff --git a/src/main/java/org/apache/commons/collections4/MultiValuedMap.java b/src/main/java/org/apache/commons/collections4/MultiValuedMap.java index d7401987a1..e3da181a38 100644 --- a/src/main/java/org/apache/commons/collections4/MultiValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/MultiValuedMap.java @@ -181,6 +181,11 @@ default MultiValuedMap inverted() { *

* A map iterator is an efficient way of iterating over maps. There is no need to access the entries collection or use {@code Map.Entry} objects. *

+ *

+ * The iterator visits one key-value mapping at a time, so a key with several values is returned once per value. The implementations in this + * library do not support {@link MapIterator#setValue(Object)} and throw an {@link UnsupportedOperationException} from it; to replace a value, + * remove the mapping, with {@link MapIterator#remove()} or {@link #removeMapping(Object, Object)}, and {@link #put(Object, Object) put} the new one. + *

* * @return A map iterator. */ diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java index 7973e378a0..d3213bc3f3 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java @@ -344,6 +344,14 @@ public void remove() { it.remove(); } + /** + * Always throws {@link UnsupportedOperationException}, as the entries of a multivalued map are read-only. + * + * @param value Ignored. + * @return Never returns normally. + * @throws IllegalStateException if {@link #next()} has not been called yet. + * @throws UnsupportedOperationException Always thrown otherwise. + */ @Override public V setValue(final V value) { if (current == null) { @@ -747,6 +755,13 @@ public Set keySet() { return getMap().keySet(); } + /** + * {@inheritDoc} + *

+ * The returned iterator does not support {@link MapIterator#setValue(Object)}: the entries it iterates are read-only, so {@code setValue} + * throws an {@link UnsupportedOperationException}. + *

+ */ @Override public MapIterator mapIterator() { if (isEmpty()) {