You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2015/11/22 22:11:50 UTC
svn commit: r1715695 - in /commons/proper/collections/trunk/src:
main/java/org/apache/commons/collections4/
main/java/org/apache/commons/collections4/multimap/
test/java/org/apache/commons/collections4/map/
test/java/org/apache/commons/collections4/mul...
Author: tn
Date: Sun Nov 22 21:11:49 2015
New Revision: 1715695
URL: http://svn.apache.org/viewvc?rev=1715695&view=rev
Log:
[COLLECTIONS-508] Added asMap() implementation for MultiValuedMaps.
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/map/AbstractMapTest.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/MultiValuedMap.java Sun Nov 22 21:11:49 2015
@@ -17,6 +17,7 @@
package org.apache.commons.collections4;
import java.util.Collection;
+import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -289,8 +290,18 @@ public interface MultiValuedMap<K, V> {
Collection<V> values();
/**
- * Returns a {@link Map} view of this MultiValuedMap with a Collection as
- * its value. The Collection holds all the values mapped to that key.
+ * Returns a view of this multi-valued map as a {@code Map} from each distinct
+ * key to the non-empty collection of that key's associated values.
+ * <p>
+ * Note that {@code this.asMap().get(k)} is equivalent to {@code this.get(k)}
+ * only when {@code k} is a key contained in the multi-valued map; otherwise it
+ * returns {@code null} as opposed to an empty collection.
+ * <p>
+ * Changes to the returned map or the collections that serve as its values
+ * will update the underlying multi-valued map, and vice versa. The map does
+ * not support {@code put} or {@code putAll}, nor do its entries support
+ * {@link Map.Entry#setValue setValue} and iterators support
+ * {@link Iterator#remove remove}.
*
* @return a map view of the mappings in this multi-valued map
*/
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java Sun Nov 22 21:11:49 2015
@@ -79,6 +79,11 @@ public abstract class AbstractListValued
*/
@Override
public List<V> get(final K key) {
+ return wrappedCollection(key);
+ }
+
+ @Override
+ List<V> wrappedCollection(final K key) {
return new WrappedList(key);
}
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java Sun Nov 22 21:11:49 2015
@@ -20,6 +20,8 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -33,11 +35,13 @@ import org.apache.commons.collections4.M
import org.apache.commons.collections4.MultiSet;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.Transformer;
+import org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
import org.apache.commons.collections4.iterators.EmptyMapIterator;
import org.apache.commons.collections4.iterators.IteratorChain;
import org.apache.commons.collections4.iterators.LazyIteratorChain;
import org.apache.commons.collections4.iterators.TransformIterator;
import org.apache.commons.collections4.keyvalue.AbstractMapEntry;
+import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry;
import org.apache.commons.collections4.multiset.AbstractMultiSet;
import org.apache.commons.collections4.multiset.UnmodifiableMultiSet;
@@ -61,6 +65,9 @@ public abstract class AbstractMultiValue
/** The KeyMultiSet view */
private transient MultiSet<K> keysMultiSetView;
+ /** The AsMap view */
+ private transient AsMap asMapView;
+
/** The map used to store the data */
private transient Map<K, Collection<V>> map;
@@ -140,6 +147,10 @@ public abstract class AbstractMultiValue
*/
@Override
public Collection<V> get(final K key) {
+ return wrappedCollection(key);
+ }
+
+ Collection<V> wrappedCollection(final K key) {
return new WrappedCollection(key);
}
@@ -324,10 +335,8 @@ public abstract class AbstractMultiValue
}
@Override
- @SuppressWarnings("unchecked")
public Map<K, Collection<V>> asMap() {
- // TODO: return a view of the map
- return (Map<K, Collection<V>>) getMap();
+ return asMapView != null ? asMapView : (asMapView = new AsMap(map));
}
/**
@@ -767,6 +776,131 @@ public abstract class AbstractMultiValue
}
}
+ /**
+ * Inner class that provides the AsMap view.
+ */
+ private class AsMap extends AbstractMap<K, Collection<V>> {
+ final transient Map<K, Collection<V>> decoratedMap;
+
+ AsMap(final Map<K, Collection<V>> map) {
+ this.decoratedMap = map;
+ }
+
+ @Override
+ public Set<Map.Entry<K, Collection<V>>> entrySet() {
+ return new AsMapEntrySet();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return decoratedMap.containsKey(key);
+ }
+
+ @Override
+ public Collection<V> get(Object key) {
+ Collection<V> collection = decoratedMap.get(key);
+ if (collection == null) {
+ return null;
+ }
+ @SuppressWarnings("unchecked")
+ K k = (K) key;
+ return wrappedCollection(k);
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return AbstractMultiValuedMap.this.keySet();
+ }
+
+ @Override
+ public int size() {
+ return decoratedMap.size();
+ }
+
+ @Override
+ public Collection<V> remove(Object key) {
+ Collection<V> collection = decoratedMap.remove(key);
+ if (collection == null) {
+ return null;
+ }
+
+ final Collection<V> output = createCollection();
+ output.addAll(collection);
+ collection.clear();
+ return output;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ return this == object || decoratedMap.equals(object);
+ }
+
+ @Override
+ public int hashCode() {
+ return decoratedMap.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return decoratedMap.toString();
+ }
+
+ @Override
+ public void clear() {
+ AbstractMultiValuedMap.this.clear();
+ }
+
+ class AsMapEntrySet extends AbstractSet<Map.Entry<K, Collection<V>>> {
+
+ @Override
+ public Iterator<Map.Entry<K, Collection<V>>> iterator() {
+ return new AsMapEntrySetIterator(decoratedMap.entrySet().iterator());
+ }
+
+ @Override
+ public int size() {
+ return AsMap.this.size();
+ }
+
+ @Override
+ public void clear() {
+ AsMap.this.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return decoratedMap.entrySet().contains(o);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if (!contains(o)) {
+ return false;
+ }
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
+ AbstractMultiValuedMap.this.remove(entry.getKey());
+ return true;
+ }
+ }
+
+ /**
+ * EntrySet iterator for the asMap view.
+ */
+ class AsMapEntrySetIterator extends AbstractIteratorDecorator<Map.Entry<K, Collection<V>>> {
+
+ AsMapEntrySetIterator(Iterator<Map.Entry<K, Collection<V>>> iterator) {
+ super(iterator);
+ }
+
+ @Override
+ public Map.Entry<K, Collection<V>> next() {
+ final Map.Entry<K, Collection<V>> entry = super.next();
+ final K key = entry.getKey();
+ return new UnmodifiableMapEntry<K, Collection<V>>(key, wrappedCollection(key));
+ }
+ }
+ }
+
//-----------------------------------------------------------------------
/**
* Write the map out using a custom routine.
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java Sun Nov 22 21:11:49 2015
@@ -78,6 +78,11 @@ public abstract class AbstractSetValuedM
*/
@Override
public Set<V> get(final K key) {
+ return wrappedCollection(key);
+ }
+
+ @Override
+ Set<V> wrappedCollection(final K key) {
return new WrappedSet(key);
}
Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/map/AbstractMapTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/map/AbstractMapTest.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/map/AbstractMapTest.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/map/AbstractMapTest.java Sun Nov 22 21:11:49 2015
@@ -287,6 +287,10 @@ public abstract class AbstractMapTest<K,
return true;
}
+ public boolean areEqualElementsDistinguishable() {
+ return false;
+ }
+
/**
* Returns the set of keys in the mappings used to test the map. This
* method must return an array with the same length as {@link
@@ -1588,6 +1592,11 @@ public abstract class AbstractMapTest<K,
}
@Override
+ public boolean areEqualElementsDistinguishable() {
+ return AbstractMapTest.this.areEqualElementsDistinguishable();
+ }
+
+ @Override
public boolean isTestSerialization() {
return false;
}
Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java?rev=1715695&r1=1715694&r2=1715695&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java Sun Nov 22 21:11:49 2015
@@ -683,30 +683,6 @@ public abstract class AbstractMultiValue
assertTrue(col.contains("uno"));
}
- @SuppressWarnings("unchecked")
- public void testAsMapPut() {
- if (!isAddSupported()) {
- return;
- }
- resetEmpty();
- Map<K, Collection<V>> mapCol = getMap().asMap();
- Collection<V> col = (Collection<V>) Arrays.asList("un", "uno");
- mapCol.put((K) "one", col);
- assertEquals(2, getMap().size());
- assertTrue(getMap().containsKey("one"));
- assertTrue(getMap().containsValue("un"));
- assertTrue(getMap().containsValue("uno"));
-
- resetFull();
- mapCol = getMap().asMap();
- col = mapCol.get("one");
- col.add((V) "one");
- assertEquals(7, getMap().size());
- assertTrue(getMap().containsValue("one"));
- assertTrue(getMap().containsValue("un"));
- assertTrue(getMap().containsValue("uno"));
- }
-
public void testAsMapRemove() {
if (!isRemoveSupported()) {
return;
@@ -1141,23 +1117,31 @@ public abstract class AbstractMultiValue
@Override
public boolean isPutAddSupported() {
- return AbstractMultiValuedMapTest.this.isAddSupported();
+ return false;
}
@Override
public boolean isPutChangeSupported() {
- return AbstractMultiValuedMapTest.this.isAddSupported();
+ return false;
}
@Override
public boolean isRemoveSupported() {
return AbstractMultiValuedMapTest.this.isRemoveSupported();
}
+
+ @Override
+ public boolean areEqualElementsDistinguishable() {
+ // work-around for a problem with the EntrySet: the entries contain
+ // the wrapped collection, which will be automatically cleared
+ // when the associated key is removed from the map as the collection
+ // is not cached atm.
+ return true;
+ }
@Override
public boolean isTestSerialization() {
return false;
}
-
}
}