[COLLECTIONS-237] Added MultiValueMap.iterator() and clarified javadoc for entrySet().

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1476553 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2013-04-27 11:08:26 +00:00
parent 50bd9f108b
commit c9e1e5c8f5
3 changed files with 90 additions and 1 deletions

View File

@ -367,6 +367,12 @@
<action issue="COLLECTIONS-240" dev="bayard" type="update" due-to="Wouter de Vaal">
"MultiValueMap" is now serializable.
</action>
<action issue="COLLECTIONS-237" dev="tn" type="add" due-to="Nils Kaiser, Alan Mehlo">
Added method "MultiValueMap#iterator()" to return a flattened version of
"entrySet().iterator()". Clarified javadoc for "entrySet()" that the returned Entry
objects are unflattened, i.e. the Entry object for a given key contains all values
mapped to this key.
</action>
<action issue="COLLECTIONS-235" dev="bayard" type="add" due-to="Nathan Egge">
Added method "ListUtils#indexOf(List, Predicate)".
</action>

View File

@ -33,8 +33,11 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Factory;
import org.apache.commons.collections4.FunctorException;
import org.apache.commons.collections4.MultiMap;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.iterators.EmptyIterator;
import org.apache.commons.collections4.iterators.IteratorChain;
import org.apache.commons.collections4.iterators.LazyIteratorChain;
import org.apache.commons.collections4.iterators.TransformIterator;
/**
* A MultiValueMap decorates another map, allowing it to have
@ -195,7 +198,7 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
* Other values attached to that key are unaffected.
* <p>
* If the last value for a key is removed, <code>null</code> will be returned
* from a subsequant <code>get(key)</code>.
* from a subsequent <code>get(key)</code>.
*
* @param key the key to remove from
* @param value the value to remove
@ -293,6 +296,20 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
}
}
/**
* {@inheritDoc}
* <p>
* NOTE: the returned Entry objects will contain as value a {@link Collection}
* of all values that are mapped to the given key. To get a "flattened" version
* of all mappings contained in this map, use {@link #iterator()}.
*
* @see #iterator()
*/
@Override
public Set<Entry<K, Object>> entrySet() {
return super.entrySet();
}
/**
* Gets a collection containing all the values in the map.
* <p>
@ -389,6 +406,48 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
return new ValuesIterator(key);
}
/**
* Gets an iterator for all mappings stored in this {@link MultiValueMap}.
* <p>
* The iterator will return multiple Entry objects with the same key
* if there are multiple values mapped to this key.
* <p>
* NOTE: calling {@link Map.Entry#setValue(Object)} on any of the returned
* elements will result in a {@link UnsupportedOperationException}.
*
* @return the iterator of all mappings in this map
* @since 4.0
*/
public Iterator<Entry<K, V>> iterator() {
final Collection<K> allKeys = new ArrayList<K>(keySet());
final Iterator<K> keyIterator = allKeys.iterator();
return new LazyIteratorChain<Entry<K, V>>() {
protected Iterator<? extends Entry<K, V>> nextIterator(int count) {
if ( ! keyIterator.hasNext() ) {
return null;
}
final K key = keyIterator.next();
final Transformer<V, Entry<K, V>> transformer = new Transformer<V, Entry<K, V>>() {
public Entry<K, V> transform(final V input) {
return new Entry<K, V>() {
public K getKey() {
return key;
}
public V getValue() {
return input;
}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
};
}
};
return new TransformIterator<V, Entry<K, V>>(new ValuesIterator(key), transformer);
}
};
}
/**
* Gets the total size of the map by counting all the values.
*

View File

@ -146,6 +146,30 @@ public class MultiValueMapTest<K, V> extends AbstractObjectTest {
assertEquals(4, map.totalSize());
}
public void testIterator() {
final MultiValueMap<K, V> map = createTestMap();
@SuppressWarnings("unchecked")
Collection<V> values = new ArrayList<V>((Collection<V>) map.values());
Iterator<Map.Entry<K, V>> iterator = map.iterator();
while (iterator.hasNext()) {
Map.Entry<K, V> entry = iterator.next();
assertTrue(map.containsValue(entry.getKey(), entry.getValue()));
assertTrue(values.contains(entry.getValue()));
assertTrue(values.remove(entry.getValue()));
}
assertTrue(values.isEmpty());
}
public void testRemoveAllViaEntryIterator() {
final MultiValueMap<K, V> map = createTestMap();
for (final Iterator<?> i = map.iterator(); i.hasNext();) {
i.next();
i.remove();
}
assertNull(map.get("one"));
assertEquals(0, map.totalSize());
}
public void testTotalSizeA() {
assertEquals(6, createTestMap().totalSize());
}