diff --git a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java index bf30d9006..5fdee52c1 100644 --- a/src/main/java/org/apache/commons/collections4/MultiMapUtils.java +++ b/src/main/java/org/apache/commons/collections4/MultiMapUtils.java @@ -23,7 +23,8 @@ import java.util.List; import java.util.Set; import org.apache.commons.collections4.bag.HashBag; -import org.apache.commons.collections4.multimap.MultiValuedHashMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; import org.apache.commons.collections4.multimap.TransformedMultiValuedMap; import org.apache.commons.collections4.multimap.UnmodifiableMultiValuedMap; @@ -52,7 +53,7 @@ public class MultiMapUtils { */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static final MultiValuedMap EMPTY_MULTI_VALUED_MAP = - UnmodifiableMultiValuedMap.unmodifiableMultiValuedMap(new MultiValuedHashMap()); + UnmodifiableMultiValuedMap.unmodifiableMultiValuedMap(new ArrayListValuedHashMap(0, 0)); /** * Returns immutable EMPTY_MULTI_VALUED_MAP with generic type safety. @@ -188,21 +189,7 @@ public class MultiMapUtils { * @return a new ListValuedMap */ public static ListValuedMap newListValuedHashMap() { - return MultiValuedHashMap.listValuedHashMap(); - } - - /** - * Creates a {@link ListValuedMap} with a {@link java.util.HashMap HashMap} as its internal - * storage which maps the keys to list of type listClass. - * - * @param the key type - * @param the value type - * @param the List class type - * @param listClass the class of the list - * @return a new {@link ListValuedMap} - */ - public static > ListValuedMap newListValuedHashMap(final Class listClass) { - return MultiValuedHashMap.listValuedHashMap(listClass); + return new ArrayListValuedHashMap(); } /** @@ -214,21 +201,7 @@ public class MultiMapUtils { * @return a new {@link SetValuedMap} */ public static SetValuedMap newSetValuedHashMap() { - return MultiValuedHashMap.setValuedHashMap(); - } - - /** - * Creates a {@link SetValuedMap} with a {@link java.util.HashMap HashMap} as its internal - * storage which maps the keys to a set of type setClass - * - * @param the key type - * @param the value type - * @param the Set class type - * @param setClass the class of the set - * @return a new {@link SetValuedMap} - */ - public static > SetValuedMap newSetValuedHashMap(final Class setClass) { - return MultiValuedHashMap.setValuedHashMap(setClass); + return new HashSetValuedHashMap(); } // MultiValuedMap Decorators diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java index dd1014eb4..d5e3237a3 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractListValuedMap.java @@ -38,34 +38,28 @@ import org.apache.commons.collections4.ListValuedMap; public abstract class AbstractListValuedMap extends AbstractMultiValuedMap implements ListValuedMap { - /** The serialization version */ - private static final long serialVersionUID = 20150612L; - /** - * A constructor that wraps, not copies - * - * @param the list type - * @param map the map to wrap, must not be null - * @param listClazz the collection class - * @throws NullPointerException if the map is null + * Constructor needed for subclass serialisation. */ - protected > AbstractListValuedMap(final Map map, Class listClazz) { - super(map, listClazz); + protected AbstractListValuedMap() { + super(); } /** * A constructor that wraps, not copies * - * @param the list type * @param map the map to wrap, must not be null - * @param listClazz the collection class - * @param initialListCapacity the initial size of the values list - * @throws NullPointerException if the map is null - * @throws IllegalArgumentException if initialListCapacity is negative + * @throws NullPointerException if the map is null */ - protected > AbstractListValuedMap(final Map map, Class listClazz, - final int initialListCapacity) { - super(map, listClazz, initialListCapacity); + protected AbstractListValuedMap(final Map> map) { + super(map); + } + + // ----------------------------------------------------------------------- + @Override + @SuppressWarnings("unchecked") + protected Map> getMap() { + return (Map>) super.getMap(); } /** @@ -73,10 +67,9 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap * @return a new list */ @Override - protected List createCollection() { - return (List) super.createCollection(); - } + protected abstract List createCollection(); + // ----------------------------------------------------------------------- /** * Gets the list of values associated with the specified key. This would * return an empty list in case the mapping is not present @@ -100,25 +93,10 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap */ @Override public List remove(Object key) { - return ListUtils.emptyIfNull((List) getMap().remove(key)); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof ListValuedMap) { - return asMap().equals(((ListValuedMap) obj).asMap()); - } - return false; - } - - @Override - public int hashCode() { - return asMap().hashCode(); + return ListUtils.emptyIfNull(getMap().remove(key)); } + // ----------------------------------------------------------------------- /** * Wrapped list to handle add and remove on the list returned by get(object) */ @@ -130,7 +108,7 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap @Override protected List getMapping() { - return (List) getMap().get(key); + return getMap().get(key); } @Override @@ -237,13 +215,13 @@ public abstract class AbstractListValuedMap extends AbstractMultiValuedMap public ValuesListIterator(final K key) { this.key = key; - this.values = ListUtils.emptyIfNull((List) getMap().get(key)); + this.values = ListUtils.emptyIfNull(getMap().get(key)); this.iterator = values.listIterator(); } public ValuesListIterator(final K key, int index) { this.key = key; - this.values = ListUtils.emptyIfNull((List) getMap().get(key)); + this.values = ListUtils.emptyIfNull(getMap().get(key)); this.iterator = values.listIterator(index); } 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 fe0a77076..f1a1e5a01 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMap.java @@ -16,7 +16,9 @@ */ package org.apache.commons.collections4.multimap; -import java.io.Serializable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Array; import java.util.AbstractCollection; import java.util.ArrayList; @@ -27,13 +29,11 @@ import java.util.Map.Entry; import java.util.Set; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.Factory; import org.apache.commons.collections4.IteratorUtils; import org.apache.commons.collections4.MapIterator; import org.apache.commons.collections4.MultiSet; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.Transformer; -import org.apache.commons.collections4.functors.InstantiateFactory; import org.apache.commons.collections4.iterators.EmptyMapIterator; import org.apache.commons.collections4.iterators.IteratorChain; import org.apache.commons.collections4.iterators.LazyIteratorChain; @@ -50,13 +50,7 @@ import org.apache.commons.collections4.set.UnmodifiableSet; * @since 4.1 * @version $Id$ */ -public abstract class AbstractMultiValuedMap implements MultiValuedMap, Serializable { - - /** Serialization Version */ - private static final long serialVersionUID = 20150612L; - - /** The factory for creating value collections. */ - private final Factory> collectionFactory; +public abstract class AbstractMultiValuedMap implements MultiValuedMap { /** The values view */ private transient Collection valuesView; @@ -68,60 +62,55 @@ public abstract class AbstractMultiValuedMap implements MultiValuedMap> map; + private transient Map> map; + + /** + * Constructor needed for subclass serialisation. + */ + protected AbstractMultiValuedMap() { + super(); + } /** * Constructor that wraps (not copies). * * @param the collection type * @param map the map to wrap, must not be null - * @param collectionClazz the collection class * @throws NullPointerException if the map is null */ @SuppressWarnings("unchecked") - protected > AbstractMultiValuedMap(final Map map, - final Class collectionClazz) { + protected AbstractMultiValuedMap(final Map> map) { if (map == null) { throw new NullPointerException("Map must not be null."); } this.map = (Map>) map; - this.collectionFactory = new InstantiateFactory(collectionClazz); - } - - /** - * Constructor that wraps (not copies). - * - * @param the collection type - * @param map the map to wrap, must not be null - * @param collectionClazz the collection class - * @param initialCollectionCapacity the initial capacity of the collection - * @throws NullPointerException if the map is null - * @throws IllegalArgumentException if initialCollectionCapacity is negative - */ - @SuppressWarnings("unchecked") - protected > AbstractMultiValuedMap(final Map map, - final Class collectionClazz, final int initialCollectionCapacity) { - if (map == null) { - throw new NullPointerException("Map must not be null."); - } - if (initialCollectionCapacity < 0) { - throw new IllegalArgumentException("InitialCapacity must not be negative."); - } - this.map = (Map>) map; - this.collectionFactory = new InstantiateFactory(collectionClazz, - new Class[] { Integer.TYPE }, - new Object[] { Integer.valueOf(initialCollectionCapacity) }); } + // ----------------------------------------------------------------------- /** * Gets the map being wrapped. * * @return the wrapped map */ - protected Map> getMap() { + protected Map> getMap() { return map; } + /** + * Sets the map being wrapped. + *

+ * NOTE: this method should only be used during deserialization + * + * @param map the map to wrap + */ + @SuppressWarnings("unchecked") + protected void setMap(Map> map) { + this.map = (Map>) map; + } + + protected abstract Collection createCollection(); + + // ----------------------------------------------------------------------- @Override public boolean containsKey(Object key) { return getMap().containsKey(key); @@ -250,7 +239,7 @@ public abstract class AbstractMultiValuedMap implements MultiValuedMap implements MultiValuedMap> asMap() { - return getMap(); + // TODO: return a view of the map + return (Map>) getMap(); } /** @@ -373,18 +364,12 @@ public abstract class AbstractMultiValuedMap implements MultiValuedMap createCollection() { - return collectionFactory.create(); + return asMap().toString(); } // ----------------------------------------------------------------------- @@ -906,4 +891,44 @@ public abstract class AbstractMultiValuedMap implements MultiValuedMap> entry : map.entrySet()) { + out.writeObject(entry.getKey()); + out.writeInt(entry.getValue().size()); + for (final V value : entry.getValue()) { + out.writeObject(value); + } + } + } + + /** + * Read the map in using a custom routine. + * @param in the input stream + * @throws IOException any of the usual I/O related exceptions + * @throws ClassNotFoundException if the stream contains an object which class can not be loaded + * @throws ClassCastException if the stream does not contain the correct objects + */ + protected void doReadObject(final ObjectInputStream in) + throws IOException, ClassNotFoundException { + final int entrySize = in.readInt(); + for (int i = 0; i < entrySize; i++) { + @SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect + final K key = (K) in.readObject(); + final Collection values = get(key); + final int valueSize = in.readInt(); + for (int j = 0; j < valueSize; j++) { + @SuppressWarnings("unchecked") // see above + V value = (V) in.readObject(); + values.add(value); + } + } + } + } diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapDecorator.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapDecorator.java index 525cfc58c..ff520caa4 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapDecorator.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapDecorator.java @@ -61,6 +61,7 @@ public abstract class AbstractMultiValuedMapDecorator this.map = map; } + // ----------------------------------------------------------------------- /** * The decorated multi-valued map. * @@ -70,6 +71,7 @@ public abstract class AbstractMultiValuedMapDecorator return map; } + // ----------------------------------------------------------------------- @Override public int size() { return decorated().size(); diff --git a/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java index 5355f6d66..bcfa20af3 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/AbstractSetValuedMap.java @@ -36,36 +36,38 @@ import org.apache.commons.collections4.SetValuedMap; public abstract class AbstractSetValuedMap extends AbstractMultiValuedMap implements SetValuedMap { - /** Serialization version */ - private static final long serialVersionUID = 20150612L; - /** - * A constructor that wraps, not copies - * - * @param the set type - * @param map the map to wrap, must not be null - * @param setClazz the collection class - * @throws NullPointerException if the map is null + * Constructor needed for subclass serialisation. */ - protected > AbstractSetValuedMap(Map map, Class setClazz) { - super(map, setClazz); + protected AbstractSetValuedMap() { + super(); } /** * A constructor that wraps, not copies * - * @param the set type * @param map the map to wrap, must not be null - * @param setClazz the collection class - * @param initialSetCapacity the initial size of the values set * @throws NullPointerException if the map is null - * @throws IllegalArgumentException if initialSetCapacity is negative */ - protected > AbstractSetValuedMap(Map map, Class setClazz, - int initialSetCapacity) { - super(map, setClazz, initialSetCapacity); + protected AbstractSetValuedMap(Map> map) { + super(map); } + // ----------------------------------------------------------------------- + @Override + @SuppressWarnings("unchecked") + protected Map> getMap() { + return (Map>) super.getMap(); + } + + /** + * Creates a new value collection using the provided factory. + * @return a new list + */ + @Override + protected abstract Set createCollection(); + + // ----------------------------------------------------------------------- /** * Gets the set of values associated with the specified key. This would * return an empty set in case the mapping is not present @@ -90,25 +92,10 @@ public abstract class AbstractSetValuedMap extends AbstractMultiValuedMap< */ @Override public Set remove(Object key) { - return SetUtils.emptyIfNull((Set) getMap().remove(key)); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof SetValuedMap) { - return asMap().equals(((SetValuedMap) obj).asMap()); - } - return false; - } - - @Override - public int hashCode() { - return asMap().hashCode(); + return SetUtils.emptyIfNull(getMap().remove(key)); } + // ----------------------------------------------------------------------- /** * Wrapped set to handle add and remove on the collection returned by * {@code get(Object)}. diff --git a/src/main/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java b/src/main/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java new file mode 100644 index 000000000..2d4fa648a --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMap.java @@ -0,0 +1,128 @@ +package org.apache.commons.collections4.multimap; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.collections4.ListValuedMap; +import org.apache.commons.collections4.MultiValuedMap; + +/** + * Implements a {@link ListValuedMap}, using a {@link HashMap} to provide data + * storage and {@link ArrayList}s as value collections. This is the standard + * implementation of a ListValuedMap. + *

+ * Note that ArrayListValuedHashMap is not synchronized and is not + * thread-safe. If you wish to use this map from multiple threads + * concurrently, you must use appropriate synchronization. This class may throw + * exceptions when accessed by concurrent threads without synchronization. + * + * @since 4.1 + * @version $Id$ + */ +public class ArrayListValuedHashMap extends AbstractListValuedMap + implements Serializable { + + /** Serialization Version */ + private static final long serialVersionUID = 20151118L; + + /** + * The initial map capacity used when none specified in constructor. + */ + private static final int DEFAULT_INITIAL_MAP_CAPACITY = 16; + + /** + * The initial list capacity when using none specified in constructor. + */ + private static final int DEFAULT_INITIAL_LIST_CAPACITY = 3; + + /** + * The initial list capacity when creating a new value collection. + */ + private final int initialListCapacity; + + /** + * Creates an empty ArrayListValuedHashMap with the default initial + * map capacity (16) and the default initial list capacity (3). + */ + public ArrayListValuedHashMap() { + this(DEFAULT_INITIAL_MAP_CAPACITY, DEFAULT_INITIAL_LIST_CAPACITY); + } + + /** + * Creates an empty ArrayListValuedHashMap with the default initial + * map capacity (16) and the specified initial list capacity. + * + * @param initialListCapacity the initial capacity used for value collections + */ + public ArrayListValuedHashMap(int initialListCapacity) { + this(DEFAULT_INITIAL_MAP_CAPACITY, initialListCapacity); + } + + /** + * Creates an empty ArrayListValuedHashMap with the specified initial + * map and list capacities. + * + * @param initialMapCapacity the initial hashmap capacity + * @param initialListCapacity the initial capacity used for value collections + */ + public ArrayListValuedHashMap(int initialMapCapacity, int initialListCapacity) { + super(new HashMap>(initialMapCapacity)); + this.initialListCapacity = initialListCapacity; + } + + /** + * Creates an ArrayListValuedHashMap copying all the mappings of the given map. + * + * @param map a MultiValuedMap to copy into this map + */ + public ArrayListValuedHashMap(final MultiValuedMap map) { + this(map.size(), DEFAULT_INITIAL_LIST_CAPACITY); + super.putAll(map); + } + + /** + * Creates an ArrayListValuedHashMap copying all the mappings of the given map. + * + * @param map a Map to copy into this map + */ + public ArrayListValuedHashMap(final Map map) { + this(map.size(), DEFAULT_INITIAL_LIST_CAPACITY); + super.putAll(map); + } + + // ----------------------------------------------------------------------- + @Override + protected ArrayList createCollection() { + return new ArrayList(initialListCapacity); + } + + // ----------------------------------------------------------------------- + /** + * Trims the capacity of all value collections to their current size. + */ + public void trimToSize() { + for (Collection coll : getMap().values()) { + final ArrayList list = (ArrayList) coll; + list.trimToSize(); + } + } + + // ----------------------------------------------------------------------- + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + doWriteObject(oos); + } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + setMap(new HashMap>()); + doReadObject(ois); + } + +} diff --git a/src/main/java/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java b/src/main/java/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java new file mode 100644 index 000000000..5737368c8 --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/multimap/HashSetValuedHashMap.java @@ -0,0 +1,116 @@ +package org.apache.commons.collections4.multimap; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.SetValuedMap; + +/** + * Implements a {@link SetValuedMap}, using a {@link HashMap} to provide data + * storage and {@link HashSet}s as value collections. This is the standard + * implementation of a SetValuedMap. + *

+ * Note that HashSetValuedHashMap is not synchronized and is not + * thread-safe. If you wish to use this map from multiple threads + * concurrently, you must use appropriate synchronization. This class may throw + * exceptions when accessed by concurrent threads without synchronization. + * + * @since 4.1 + * @version $Id$ + */ +public class HashSetValuedHashMap extends AbstractSetValuedMap + implements Serializable { + + /** Serialization Version */ + private static final long serialVersionUID = 20151118L; + + /** + * The initial map capacity used when none specified in constructor. + */ + private static final int DEFAULT_INITIAL_MAP_CAPACITY = 16; + + /** + * The initial set capacity when using none specified in constructor. + */ + private static final int DEFAULT_INITIAL_SET_CAPACITY = 3; + + /** + * The initial list capacity when creating a new value collection. + */ + private final int initialSetCapacity; + + /** + * Creates an empty HashSetValuedHashMap with the default initial + * map capacity (16) and the default initial set capacity (3). + */ + public HashSetValuedHashMap() { + this(DEFAULT_INITIAL_MAP_CAPACITY, DEFAULT_INITIAL_SET_CAPACITY); + } + + /** + * Creates an empty HashSetValuedHashMap with the default initial + * map capacity (16) and the specified initial set capacity. + * + * @param initialSetCapacity the initial capacity used for value collections + */ + public HashSetValuedHashMap(int initialSetCapacity) { + this(DEFAULT_INITIAL_MAP_CAPACITY, initialSetCapacity); + } + + /** + * Creates an empty HashSetValuedHashMap with the specified initial + * map and list capacities. + * + * @param initialMapCapacity the initial hashmap capacity + * @param initialSetCapacity the initial capacity used for value collections + */ + public HashSetValuedHashMap(int initialMapCapacity, int initialSetCapacity) { + super(new HashMap>(initialMapCapacity)); + this.initialSetCapacity = initialSetCapacity; + } + + /** + * Creates an HashSetValuedHashMap copying all the mappings of the given map. + * + * @param map a MultiValuedMap to copy into this map + */ + public HashSetValuedHashMap(final MultiValuedMap map) { + this(map.size(), DEFAULT_INITIAL_SET_CAPACITY); + super.putAll(map); + } + + /** + * Creates an HashSetValuedHashMap copying all the mappings of the given map. + * + * @param map a Map to copy into this map + */ + public HashSetValuedHashMap(final Map map) { + this(map.size(), DEFAULT_INITIAL_SET_CAPACITY); + super.putAll(map); + } + + // ----------------------------------------------------------------------- + @Override + protected HashSet createCollection() { + return new HashSet(initialSetCapacity); + } + + // ----------------------------------------------------------------------- + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + doWriteObject(oos); + } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + setMap(new HashMap>()); + doReadObject(ois); + } + +} diff --git a/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java b/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java deleted file mode 100644 index d0a5704a9..000000000 --- a/src/main/java/org/apache/commons/collections4/multimap/MultiValuedHashMap.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.collections4.multimap; - -import java.util.ArrayList; -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.ListValuedMap; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.SetValuedMap; - -/** - * Implements a {@link MultiValuedMap}, using a {@link HashMap} to provide data - * storage. This is the standard implementation of a MultiValuedMap - *

- * A MultiValuedMap is a Map with slightly different semantics. - * Putting a value into the map will add the value to a Collection at that key. - * Getting a value will return a Collection, holding all the values put to that - * key - *

- * In addition, this implementation allows the type of collection used for the - * values to be controlled. By default, an ArrayList is used, - * however a Class to instantiate the value - * collection may be specified. - *

- * Note that MultiValuedHashMap is not synchronized and is not - * thread-safe. If you wish to use this map from multiple threads - * concurrently, you must use appropriate synchronization. This class may throw - * exceptions when accessed by concurrent threads without synchronization. - * - * @since 4.1 - * @version $Id$ - */ -public class MultiValuedHashMap extends AbstractMultiValuedMap { - - /** Serialization Version */ - private static final long serialVersionUID = 20150612L; - - /** - * The initial capacity used when none specified in constructor. - */ - static final int DEFAULT_INITIAL_CAPACITY = 16; - - /** - * The load factor used when none specified in constructor. - */ - static final float DEFAULT_LOAD_FACTOR = 0.75f; - - /** - * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal - * storage - * - * @param the key type - * @param the value type - * @return a new ListValuedMap - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static ListValuedMap listValuedHashMap() { - return new ListValuedHashMap(ArrayList.class); - } - - /** - * Creates a {@link ListValuedMap} with a {@link HashMap} as its internal - * storage which maps the keys to list of type listClass - * - * @param the key type - * @param the value type - * @param the List class type - * @param listClass the class of the list - * @return a new ListValuedMap - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static > ListValuedMap listValuedHashMap(final Class listClass) { - return new ListValuedHashMap(listClass); - } - - /** - * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal - * storage - * - * @param the key type - * @param the value type - * @return a new SetValuedMap - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static SetValuedMap setValuedHashMap() { - return new SetValuedHashMap(HashSet.class); - } - - /** - * Creates a {@link SetValuedMap} with a {@link HashMap} as its internal - * storage which maps the keys to a set of type setClass - * - * @param the key type - * @param the value type - * @param the Set class type - * @param setClass the class of the set - * @return a new SetValuedMap - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static > SetValuedMap setValuedHashMap(final Class setClass) { - return new SetValuedHashMap(setClass); - } - - /** - * Creates a MultiValueMap based on a HashMap with the default - * initial capacity (16) and the default load factor (0.75), which stores - * the multiple values in an ArrayList. - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap() { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class); - } - - /** - * Creates a MultiValueMap based on a HashMap with the initial - * capacity and the default load factor (0.75), which stores the multiple - * values in an ArrayList. - * - * @param initialCapacity the initial capacity of the underlying hash map - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR, ArrayList.class); - } - - /** - * Creates a MultiValueMap based on a HashMap with the initial - * capacity and the load factor, which stores the multiple values in an - * ArrayList. - * - * @param initialCapacity the initial capacity of the underlying hash map - * @param loadFactor the load factor of the underlying hash map - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap(int initialCapacity, float loadFactor) { - this(initialCapacity, loadFactor, ArrayList.class); - } - - /** - * Creates a MultiValueMap based on a HashMap with the initial - * capacity and the load factor, which stores the multiple values in an - * ArrayList with the initial collection capacity. - * - * @param initialCapacity the initial capacity of the underlying hash map - * @param loadFactor the load factor of the underlying hash map - * @param initialCollectionCapacity the initial capacity of the Collection of values - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap(int initialCapacity, float loadFactor, int initialCollectionCapacity) { - this(initialCapacity, loadFactor, ArrayList.class, initialCollectionCapacity); - } - - /** - * Creates a MultiValuedHashMap copying all the mappings of the given map. - * - * @param map a MultiValuedMap to copy into this map - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap(final MultiValuedMap map) { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class); - super.putAll(map); - } - - /** - * Creates a MultiValuedHashMap copying all the mappings of the given map. - * - * @param map a Map to copy into this map - */ - @SuppressWarnings("unchecked") - public MultiValuedHashMap(final Map map) { - this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, ArrayList.class); - super.putAll(map); - } - - /** - * Creates a MultiValuedHashMap which creates the value collections using - * the supplied collectionClazz. - * - * @param initialCapacity the initial capacity of the underlying - * HashMap - * @param loadFactor the load factor of the underlying HashMap - * @param the collection type - * @param collectionClazz the class of the Collection to use to - * create the value collections - */ - protected > MultiValuedHashMap(int initialCapacity, float loadFactor, - final Class collectionClazz) { - super(new HashMap>(initialCapacity, loadFactor), collectionClazz); - } - - /** - * Creates a MultiValuedHashMap which creates the value collections using - * the supplied collectionClazz and the initial collection capacity. - * - * @param the collection type - * @param initialCapacity the initial capacity of the underlying HashMap - * @param loadFactor the load factor of the underlying HashMap - * @param initialCollectionCapacity the initial capacity of the Collection - * @param collectionClazz the class of the Collection to use to create the value collections - */ - protected > MultiValuedHashMap(int initialCapacity, float loadFactor, - final Class collectionClazz, int initialCollectionCapacity) { - super(new HashMap>(initialCapacity, loadFactor), collectionClazz, - initialCollectionCapacity); - } - - /** Inner class for ListValuedMap */ - private static class ListValuedHashMap extends AbstractListValuedMap { - - private static final long serialVersionUID = 20150612L; - - public > ListValuedHashMap(Class listClazz) { - super(new HashMap>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), listClazz); - } - - public > ListValuedHashMap(Class listClazz, int initialListCapacity) { - super(new HashMap>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), listClazz, - initialListCapacity); - } - - } - - /** Inner class for SetValuedMap */ - private static class SetValuedHashMap extends AbstractSetValuedMap { - - private static final long serialVersionUID = 20150612L; - - public > SetValuedHashMap(Class setClazz) { - super(new HashMap>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), setClazz); - } - - public > SetValuedHashMap(Class setClazz, int initialSetCapacity) { - super(new HashMap>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR), setClazz, - initialSetCapacity); - } - - } - -} diff --git a/src/main/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMap.java b/src/main/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMap.java index f0edd332d..93a4a8b38 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMap.java +++ b/src/main/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMap.java @@ -91,7 +91,7 @@ public class TransformedMultiValuedMap extends AbstractMultiValuedMapDecor final TransformedMultiValuedMap decorated = new TransformedMultiValuedMap(map, keyTransformer, valueTransformer); if (!map.isEmpty()) { - final MultiValuedMap mapCopy = new MultiValuedHashMap(map); + final MultiValuedMap mapCopy = new ArrayListValuedHashMap(map); decorated.clear(); decorated.putAll(mapCopy); } diff --git a/src/main/java/org/apache/commons/collections4/multimap/package-info.java b/src/main/java/org/apache/commons/collections4/multimap/package-info.java index ace5aa153..030d3fe17 100644 --- a/src/main/java/org/apache/commons/collections4/multimap/package-info.java +++ b/src/main/java/org/apache/commons/collections4/multimap/package-info.java @@ -20,9 +20,8 @@ *

* The following implementations are provided in the package: *

    - *
  • MultiValuedHashMap - implementation that uses a HashMap to store the data - *
  • ListValuedHashMap - implementation of a ListValuedMap using a HashMap as data store - *
  • SetValuedHashMap - implementation of a SetValuedMap using a HashMap as data store + *
  • ArrayListValuedHashMap - ListValuedMap implementation using a HashMap/ArrayList + *
  • HashSetValuedHashMap - SetValuedMap implementation using a HashMap/HashSet *
*

* The following decorators are provided in the package: diff --git a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java index 865052559..3ce5d9f00 100644 --- a/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/MultiMapUtilsTest.java @@ -26,7 +26,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; -import org.apache.commons.collections4.multimap.MultiValuedHashMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.Test; /** @@ -64,20 +64,20 @@ public class MultiMapUtilsTest { public void testEmptyIfNull() { assertTrue(MultiMapUtils.emptyIfNull(null).isEmpty()); - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); map.put("item", "value"); assertFalse(MultiMapUtils.emptyIfNull(map).isEmpty()); } @Test public void testIsEmptyWithEmptyMap() { - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); assertEquals(true, MultiMapUtils.isEmpty(map)); } @Test public void testIsEmptyWithNonEmptyMap() { - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); map.put("item", "value"); assertEquals(false, MultiMapUtils.isEmpty(map)); } @@ -93,7 +93,7 @@ public class MultiMapUtilsTest { assertNull(MultiMapUtils.getCollection(null, "key1")); String values[] = { "v1", "v2", "v3" }; - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); for (String val : values) { map.put("key1", val); } @@ -109,7 +109,7 @@ public class MultiMapUtilsTest { assertNull(MultiMapUtils.getValuesAsList(null, "key1")); String values[] = { "v1", "v2", "v3" }; - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); for (String val : values) { map.put("key1", val); } @@ -126,7 +126,7 @@ public class MultiMapUtilsTest { assertNull(MultiMapUtils.getValuesAsList(null, "key1")); String values[] = { "v1", "v2", "v3" }; - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); for (String val : values) { map.put("key1", val); map.put("key1", val); @@ -144,7 +144,7 @@ public class MultiMapUtilsTest { assertNull(MultiMapUtils.getValuesAsBag(null, "key1")); String values[] = { "v1", "v2", "v3" }; - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); for (String val : values) { map.put("key1", val); map.put("key1", val); diff --git a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java index 01833b73c..84efedd52 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/AbstractMultiValuedMapTest.java @@ -33,6 +33,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapIterator; import org.apache.commons.collections4.MultiSet; import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.SetValuedMap; import org.apache.commons.collections4.bag.AbstractBagTest; import org.apache.commons.collections4.bag.HashBag; import org.apache.commons.collections4.collection.AbstractCollectionTest; @@ -104,10 +105,9 @@ public abstract class AbstractMultiValuedMapTest extends AbstractObjectTes return true; } - // FIXME: tests ignore to fix serialization issues @Override public boolean isTestSerialization() { - return false; + return true; } /** @@ -156,13 +156,13 @@ public abstract class AbstractMultiValuedMapTest extends AbstractObjectTes } /** - * Override to return a MultiValuedMap other than MultiValuedHashMap as the - * confirmed map. + * Override to return a MultiValuedMap other than ArrayListValuedHashMap + * as the confirmed map. * * @return a MultiValuedMap that is known to be valid */ public MultiValuedMap makeConfirmedMap() { - return new MultiValuedHashMap(); + return new ArrayListValuedHashMap(); } public MultiValuedMap getConfirmed() { @@ -762,17 +762,15 @@ public abstract class AbstractMultiValuedMapTest extends AbstractObjectTes // extend the AbstractTestMap // ----------------------------------------------------------------------- - // FIXME: tests ignore to fix serialization issues - public void xtestEmptyMapCompatibility() throws Exception { + public void testEmptyMapCompatibility() throws Exception { final MultiValuedMap map = makeObject(); final MultiValuedMap map2 = (MultiValuedMap) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map)); assertEquals("Map is empty", 0, map2.size()); } - // FIXME: tests ignore to fix serialization issues @SuppressWarnings({ "rawtypes", "unchecked" }) - public void xtestFullMapCompatibility() throws Exception { + public void testFullMapCompatibility() throws Exception { final MultiValuedMap map = makeFullMap(); final MultiValuedMap map2 = (MultiValuedMap) readExternalFormFromDisk(getCanonicalFullCollectionName(map)); @@ -1113,10 +1111,12 @@ public abstract class AbstractMultiValuedMapTest extends AbstractObjectTes @Override @SuppressWarnings("unchecked") public Collection[] getSampleValues() { + boolean isSetValuedMap = AbstractMultiValuedMapTest.this.getMap() instanceof SetValuedMap; V[] sampleValues = AbstractMultiValuedMapTest.this.getSampleValues(); Collection[] colArr = new Collection[3]; for(int i = 0; i < 3; i++) { - colArr[i] = Arrays.asList(sampleValues[i*2], sampleValues[i*2 + 1]); + Collection coll = Arrays.asList(sampleValues[i*2], sampleValues[i*2 + 1]); + colArr[i] = isSetValuedMap ? new HashSet(coll) : coll; } return colArr; } @@ -1124,10 +1124,12 @@ public abstract class AbstractMultiValuedMapTest extends AbstractObjectTes @Override @SuppressWarnings("unchecked") public Collection[] getNewSampleValues() { + boolean isSetValuedMap = AbstractMultiValuedMapTest.this.getMap() instanceof SetValuedMap; Object[] sampleValues = { "ein", "ek", "zwei", "duey", "drei", "teen" }; Collection[] colArr = new Collection[3]; for (int i = 0; i < 3; i++) { - colArr[i] = Arrays.asList((V) sampleValues[i * 2], (V) sampleValues[i * 2 + 1]); + Collection coll = Arrays.asList((V) sampleValues[i * 2], (V) sampleValues[i * 2 + 1]); + colArr[i] = isSetValuedMap ? new HashSet(coll) : coll; } return colArr; } diff --git a/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMapTest.java similarity index 52% rename from src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java rename to src/test/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMapTest.java index 447cce2df..21cf49729 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/MultiValuedHashMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/ArrayListValuedHashMapTest.java @@ -16,95 +16,41 @@ */ package org.apache.commons.collections4.multimap; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.Set; import junit.framework.Test; import org.apache.commons.collections4.BulkTest; import org.apache.commons.collections4.ListValuedMap; import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.SetValuedMap; /** - * Test MultValuedHashMap + * Test ArrayListValuedHashMap * * @since 4.1 * @version $Id$ */ -public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest { +public class ArrayListValuedHashMapTest extends AbstractMultiValuedMapTest { - public MultiValuedHashMapTest(String testName) { + public ArrayListValuedHashMapTest(String testName) { super(testName); } public static Test suite() { - return BulkTest.makeSuite(MultiValuedHashMapTest.class); + return BulkTest.makeSuite(ArrayListValuedHashMapTest.class); } + // ----------------------------------------------------------------------- @Override - public MultiValuedMap makeObject() { - final MultiValuedMap m = new MultiValuedHashMap(); - return m; - } - - @SuppressWarnings("unchecked") - public void testSetValuedMapAdd() { - final SetValuedMap setMap = MultiValuedHashMap.setValuedHashMap(); - assertTrue(setMap.get((K) "whatever") instanceof Set); - - Set set = setMap.get((K) "A"); - assertTrue(set.add((V) "a1")); - assertTrue(set.add((V) "a2")); - assertFalse(set.add((V) "a1")); - assertEquals(2, setMap.size()); - assertTrue(setMap.containsKey("A")); - } - - @SuppressWarnings("unchecked") - public void testSetValuedMapRemove() { - final SetValuedMap setMap = MultiValuedHashMap.setValuedHashMap(); - assertTrue(setMap.get((K) "whatever") instanceof Set); - - Set set = setMap.get((K) "A"); - assertTrue(set.add((V) "a1")); - assertTrue(set.add((V) "a2")); - assertFalse(set.add((V) "a1")); - assertEquals(2, setMap.size()); - assertTrue(setMap.containsKey("A")); - - assertTrue(set.remove("a1")); - assertTrue(set.remove("a2")); - assertFalse(set.remove("a1")); - - assertEquals(0, setMap.size()); - assertFalse(setMap.containsKey("A")); - } - - @SuppressWarnings("unchecked") - public void testSetValuedMapRemoveViaIterator() { - final SetValuedMap setMap = MultiValuedHashMap.setValuedHashMap(); - assertTrue(setMap.get((K) "whatever") instanceof Set); - - Set set = setMap.get((K) "A"); - set.add((V) "a1"); - set.add((V) "a2"); - set.add((V) "a1"); - - Iterator it = set.iterator(); - while (it.hasNext()) { - it.next(); - it.remove(); - } - assertEquals(0, setMap.size()); - assertFalse(setMap.containsKey("A")); + public ListValuedMap makeObject() { + return new ArrayListValuedHashMap(); } + // ----------------------------------------------------------------------- @SuppressWarnings("unchecked") public void testListValuedMapAdd() { - final ListValuedMap listMap = MultiValuedHashMap.listValuedHashMap(); + final ListValuedMap listMap = makeObject(); assertTrue(listMap.get((K) "whatever") instanceof List); List list = listMap.get((K) "A"); list.add((V) "a1"); @@ -114,7 +60,7 @@ public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest listMap = MultiValuedHashMap.listValuedHashMap(); + final ListValuedMap listMap = makeObject(); ListIterator listIt = listMap.get((K) "B").listIterator(); assertFalse(listIt.hasNext()); listIt.add((V) "b1"); @@ -128,7 +74,7 @@ public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest listMap = MultiValuedHashMap.listValuedHashMap(); + final ListValuedMap listMap = makeObject(); List list = listMap.get((K) "A"); list.add((V) "a1"); list.add((V) "a2"); @@ -145,7 +91,7 @@ public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest listMap = MultiValuedHashMap.listValuedHashMap(); + final ListValuedMap listMap = makeObject(); ListIterator listIt = listMap.get((K) "B").listIterator(); listIt.add((V) "b1"); listIt.add((V) "b2"); @@ -165,8 +111,8 @@ public class MultiValuedHashMapTest extends AbstractMultiValuedMapTest extends AbstractMultiValuedMapTest extends AbstractMultiValuedMapTest extends AbstractMultiValuedMapTest { + + public HashSetValuedHashMapTest(String testName) { + super(testName); + } + + public static Test suite() { + return BulkTest.makeSuite(HashSetValuedHashMapTest.class); + } + + // ----------------------------------------------------------------------- + @Override + public SetValuedMap makeObject() { + return new HashSetValuedHashMap(); + } + + @Override + public MultiValuedMap makeConfirmedMap() { + return new HashSetValuedHashMap(); + } + + // ----------------------------------------------------------------------- + @SuppressWarnings("unchecked") + public void testSetValuedMapAdd() { + final SetValuedMap setMap = makeObject(); + assertTrue(setMap.get((K) "whatever") instanceof Set); + + Set set = setMap.get((K) "A"); + assertTrue(set.add((V) "a1")); + assertTrue(set.add((V) "a2")); + assertFalse(set.add((V) "a1")); + assertEquals(2, setMap.size()); + assertTrue(setMap.containsKey("A")); + } + + @SuppressWarnings("unchecked") + public void testSetValuedMapRemove() { + final SetValuedMap setMap = makeObject(); + assertTrue(setMap.get((K) "whatever") instanceof Set); + + Set set = setMap.get((K) "A"); + assertTrue(set.add((V) "a1")); + assertTrue(set.add((V) "a2")); + assertFalse(set.add((V) "a1")); + assertEquals(2, setMap.size()); + assertTrue(setMap.containsKey("A")); + + assertTrue(set.remove("a1")); + assertTrue(set.remove("a2")); + assertFalse(set.remove("a1")); + + assertEquals(0, setMap.size()); + assertFalse(setMap.containsKey("A")); + } + + @SuppressWarnings("unchecked") + public void testSetValuedMapRemoveViaIterator() { + final SetValuedMap setMap = makeObject(); + assertTrue(setMap.get((K) "whatever") instanceof Set); + + Set set = setMap.get((K) "A"); + set.add((V) "a1"); + set.add((V) "a2"); + set.add((V) "a1"); + + Iterator it = set.iterator(); + while (it.hasNext()) { + it.next(); + it.remove(); + } + assertEquals(0, setMap.size()); + assertFalse(setMap.containsKey("A")); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testSetValuedMapEqualsHashCodeContract() { + SetValuedMap map1 = makeObject(); + SetValuedMap map2 = makeObject(); + + map1.put("a", "a1"); + map1.put("a", "a2"); + map2.put("a", "a2"); + map2.put("a", "a1"); + assertEquals(map1, map2); + assertEquals(map1.hashCode(), map2.hashCode()); + + map2.put("a", "a2"); + assertEquals(map1, map2); + assertEquals(map1.hashCode(), map2.hashCode()); + + map2.put("a", "a3"); + assertNotSame(map1, map2); + assertNotSame(map1.hashCode(), map2.hashCode()); + } + + public void testCreate() throws Exception { + writeExternalFormToDisk((java.io.Serializable) makeObject(), + "src/test/resources/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj"); + writeExternalFormToDisk((java.io.Serializable) makeFullMap(), + "src/test/resources/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj"); + } + +} diff --git a/src/test/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMapTest.java index fc7b0ad3a..40da941fc 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/TransformedMultiValuedMapTest.java @@ -42,18 +42,20 @@ public class TransformedMultiValuedMapTest extends AbstractMultiValuedMapT return BulkTest.makeSuite(TransformedMultiValuedMapTest.class); } + // ----------------------------------------------------------------------- @Override public MultiValuedMap makeObject() { - return TransformedMultiValuedMap.transformingMap(new MultiValuedHashMap(), + return TransformedMultiValuedMap.transformingMap(new ArrayListValuedHashMap(), TransformerUtils. nopTransformer(), TransformerUtils. nopTransformer()); } + // ----------------------------------------------------------------------- @SuppressWarnings("unchecked") public void testKeyTransformedMap() { final Object[] els = new Object[] { "1", "3", "5", "7", "2", "4", "6" }; MultiValuedMap map = TransformedMultiValuedMap.transformingMap( - new MultiValuedHashMap(), + new ArrayListValuedHashMap(), (Transformer) TransformedCollectionTest.STRING_TO_INTEGER_TRANSFORMER, null); assertEquals(0, map.size()); @@ -77,7 +79,7 @@ public class TransformedMultiValuedMapTest extends AbstractMultiValuedMapT final Object[] els = new Object[] { "1", "3", "5", "7", "2", "4", "6" }; MultiValuedMap map = TransformedMultiValuedMap.transformingMap( - new MultiValuedHashMap(), null, + new ArrayListValuedHashMap(), null, (Transformer) TransformedCollectionTest.STRING_TO_INTEGER_TRANSFORMER); assertEquals(0, map.size()); for (int i = 0; i < els.length; i++) { @@ -94,7 +96,7 @@ public class TransformedMultiValuedMapTest extends AbstractMultiValuedMapT // ----------------------------------------------------------------------- @SuppressWarnings("unchecked") public void testFactory_Decorate() { - final MultiValuedMap base = new MultiValuedHashMap(); + final MultiValuedMap base = new ArrayListValuedHashMap(); base.put((K) "A", (V) "1"); base.put((K) "B", (V) "2"); base.put((K) "C", (V) "3"); @@ -114,7 +116,7 @@ public class TransformedMultiValuedMapTest extends AbstractMultiValuedMapT @SuppressWarnings("unchecked") public void testFactory_decorateTransform() { - final MultiValuedMap base = new MultiValuedHashMap(); + final MultiValuedMap base = new ArrayListValuedHashMap(); base.put((K) "A", (V) "1"); base.put((K) "B", (V) "2"); base.put((K) "C", (V) "3"); @@ -132,11 +134,11 @@ public class TransformedMultiValuedMapTest extends AbstractMultiValuedMapT assertEquals(true, trans.get((K) "D").contains(Integer.valueOf(4))); } -// public void testCreate() throws Exception { -// writeExternalFormToDisk((java.io.Serializable) makeObject(), -// "src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj"); -// writeExternalFormToDisk((java.io.Serializable) makeFullMap(), -// "src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj"); -// } + public void testCreate() throws Exception { + writeExternalFormToDisk((java.io.Serializable) makeObject(), + "src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj"); + writeExternalFormToDisk((java.io.Serializable) makeFullMap(), + "src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj"); + } } diff --git a/src/test/java/org/apache/commons/collections4/multimap/UnmodifiableMultiValuedMapTest.java b/src/test/java/org/apache/commons/collections4/multimap/UnmodifiableMultiValuedMapTest.java index c56973299..2841ebfe9 100644 --- a/src/test/java/org/apache/commons/collections4/multimap/UnmodifiableMultiValuedMapTest.java +++ b/src/test/java/org/apache/commons/collections4/multimap/UnmodifiableMultiValuedMapTest.java @@ -47,6 +47,7 @@ public class UnmodifiableMultiValuedMapTest extends AbstractMultiValuedMap return BulkTest.makeSuite(UnmodifiableMultiValuedMapTest.class); } + // ----------------------------------------------------------------------- @Override public boolean isAddSupported() { return false; @@ -59,16 +60,18 @@ public class UnmodifiableMultiValuedMapTest extends AbstractMultiValuedMap @Override public MultiValuedMap makeObject() { - return UnmodifiableMultiValuedMap. unmodifiableMultiValuedMap(new MultiValuedHashMap()); + return UnmodifiableMultiValuedMap. unmodifiableMultiValuedMap( + new ArrayListValuedHashMap()); } @Override protected MultiValuedMap makeFullMap() { - final MultiValuedMap map = new MultiValuedHashMap(); + final MultiValuedMap map = new ArrayListValuedHashMap(); addSampleMappings(map); return UnmodifiableMultiValuedMap. unmodifiableMultiValuedMap(map); } + // ----------------------------------------------------------------------- public void testUnmodifiable() { assertTrue(makeObject() instanceof Unmodifiable); assertTrue(makeFullMap() instanceof Unmodifiable); @@ -259,11 +262,11 @@ public class UnmodifiableMultiValuedMapTest extends AbstractMultiValuedMap } } -// public void testCreate() throws Exception { -// writeExternalFormToDisk((java.io.Serializable) makeObject(), -// "src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj"); -// writeExternalFormToDisk((java.io.Serializable) makeFullMap(), -// "src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj"); -// } + public void testCreate() throws Exception { + writeExternalFormToDisk((java.io.Serializable) makeObject(), + "src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj"); + writeExternalFormToDisk((java.io.Serializable) makeFullMap(), + "src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj"); + } } diff --git a/src/test/resources/data/test/ArrayListValuedHashMap.emptyCollection.version4.1.obj b/src/test/resources/data/test/ArrayListValuedHashMap.emptyCollection.version4.1.obj new file mode 100644 index 000000000..a1df83d73 Binary files /dev/null and b/src/test/resources/data/test/ArrayListValuedHashMap.emptyCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/ArrayListValuedHashMap.fullCollection.version4.1.obj b/src/test/resources/data/test/ArrayListValuedHashMap.fullCollection.version4.1.obj new file mode 100644 index 000000000..97bb925c5 Binary files /dev/null and b/src/test/resources/data/test/ArrayListValuedHashMap.fullCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj b/src/test/resources/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj new file mode 100644 index 000000000..9e3f8e36d Binary files /dev/null and b/src/test/resources/data/test/HashSetValuedHashMap.emptyCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj b/src/test/resources/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj new file mode 100644 index 000000000..ec4dce5eb Binary files /dev/null and b/src/test/resources/data/test/HashSetValuedHashMap.fullCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj b/src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj index 291b6661e..a3135f560 100644 Binary files a/src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj and b/src/test/resources/data/test/TransformedMultiValuedMap.emptyCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj b/src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj index 46b67e9b6..2773eb3f9 100644 Binary files a/src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj and b/src/test/resources/data/test/TransformedMultiValuedMap.fullCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj b/src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj index e76555f32..86ea4576d 100644 Binary files a/src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj and b/src/test/resources/data/test/UnmodifiableMultiValuedMap.emptyCollection.version4.1.obj differ diff --git a/src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj b/src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj index c1403154f..5efc6df5b 100644 Binary files a/src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj and b/src/test/resources/data/test/UnmodifiableMultiValuedMap.fullCollection.version4.1.obj differ