Author: dlaha
Date: Fri Oct 17 10:51:23 2014
New Revision: 1632534

URL: http://svn.apache.org/r1632534
Log:
[COLLECTIONS-533] Initial commit for MultiValuedLinkedHashMap implementation & 
tests. Thanks to Geoff Schoeman.

Added:
    
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMap.java
    
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMapTest.java
    
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.emptyCollection.version4.1.obj
   (with props)
    
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.fullCollection.version4.1.obj
   (with props)
Modified:
    commons/proper/collections/trunk/pom.xml

Modified: commons/proper/collections/trunk/pom.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/pom.xml?rev=1632534&r1=1632533&r2=1632534&view=diff
==============================================================================
--- commons/proper/collections/trunk/pom.xml (original)
+++ commons/proper/collections/trunk/pom.xml Fri Oct 17 10:51:23 2014
@@ -109,7 +109,7 @@
       <id>dlaha</id>
     </developer>
   </developers>
-  
+
   <contributors>
     <contributor>
       <name>Rafael U. C. Afonso</name>
@@ -426,6 +426,9 @@
     <contributor>
       <name>Jason van Zyl</name>
     </contributor>
+    <contributor>
+      <name>Geoff Schoeman</name>
+    </contributor>
   </contributors>
 
   <dependencies>
@@ -456,13 +459,13 @@
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <maven.compiler.source>1.5</maven.compiler.source>
     <maven.compiler.target>1.5</maven.compiler.target>
-    
+
     <!--
        This is also  used to generate download_xxx file name.
        To override this when generating the download page:
-       
+
        mvn commons:download-page -Dcommons.componentid=collections
-       
+
        The above seems to change the download page name but not any other
        properties that depend on the componentid.
     -->
@@ -471,26 +474,26 @@
     <!-- Current 4.x release series -->
     <commons.release.version>4.0</commons.release.version>
     <commons.release.desc>(Java 5.0+)</commons.release.desc>
-    
+
     <!-- Previous 3.x release series -->
     <commons.release.2.version>3.2.1</commons.release.2.version>
     <commons.release.2.desc>(Requires Java 1.2 or 
later)</commons.release.2.desc>
     <!-- Override generated name -->
     
<commons.release.2.name>commons-collections-${commons.release.2.version}</commons.release.2.name>
-    
+
     <commons.jira.id>COLLECTIONS</commons.jira.id>
     <commons.jira.pid>12310465</commons.jira.pid>
     <!-- The RC version used in the staging repository URL. -->
     <commons.rc.version>RC5</commons.rc.version>
     <checkstyle.version>2.9.1</checkstyle.version>
-    
+
     <commons.site.path>collections</commons.site.path>
     
<commons.scmPubUrl>https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-collections</commons.scmPubUrl>
     
<commons.scmPubCheckoutDirectory>site-content</commons.scmPubCheckoutDirectory>
-    
+
     <!-- Override javadoc plugin version due to a vulnerability of the 
generated javadoc
          see http://jira.codehaus.org/browse/MJAVADOC-370, remove after update 
to CP 32   -->
-    <commons.javadoc.version>2.9.1</commons.javadoc.version>    
+    <commons.javadoc.version>2.9.1</commons.javadoc.version>
   </properties>
 
 
@@ -586,7 +589,7 @@
               <report>checkstyle</report>
             </reports>
           </reportSet>
-        </reportSets>         
+        </reportSets>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
@@ -615,7 +618,7 @@
         <artifactId>maven-pmd-plugin</artifactId>
         <version>2.7.1</version>
         <configuration>
-          <targetJdk>${maven.compiler.target}</targetJdk>  
+          <targetJdk>${maven.compiler.target}</targetJdk>
         </configuration>
         <reportSets>
           <reportSet>

Added: 
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMap.java
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMap.java?rev=1632534&view=auto
==============================================================================
--- 
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMap.java
 (added)
+++ 
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMap.java
 Fri Oct 17 10:51:23 2014
@@ -0,0 +1,263 @@
+/*
+ * 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.Collection;
+import java.util.LinkedHashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+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 LinkedHashMap} to 
provide data
+ * storage. This MultiValuedMap implementation the allows insertion order to be
+ * maintained.
+ * <p>
+ * A <code>MultiValuedMap</code> 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
+ * <p>
+ * In addition, this implementation allows the type of collection used for the
+ * values to be controlled. By default, an <code>LinkedList</code> is used,
+ * however a <code>Class<? extends Collection></code> to instantiate the value
+ * collection may be specified.
+ * <p>
+ * <strong>Note that MultiValuedLinkedHashMap is not synchronized and is not
+ * thread-safe.</strong> 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 MultiValuedLinkedHashMap<K, V> extends AbstractMultiValuedMap<K, 
V> implements MultiValuedMap<K, V> {
+
+    /** Serialization Version */
+    private static final long serialVersionUID = -5845183518195365857L;
+
+    /**
+     * 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 LinkedHashMap} as its 
internal
+     * storage
+     *
+     * @param <K> the key type
+     * @param <V> the value type
+     * @return a new <code>ListValuedMap</code>
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <K, V> ListValuedMap<K, V> listValuedLinkedHashMap() {
+        return new ListValuedLinkedHashMap(LinkedList.class);
+    }
+
+    /**
+     * Creates a {@link ListValuedMap} with a {@link LinkedHashMap} as its 
internal
+     * storage which maps the keys to list of type <code>listClass</code>
+     *
+     * @param <K> the key type
+     * @param <V> the value type
+     * @param <C> the List class type
+     * @param listClass the class of the list
+     * @return a new <code>ListValuedMap</code>
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <K, V, C extends List<V>> ListValuedMap<K, V> 
listValuedLinkedHashMap(final Class<C> listClass) {
+        return new ListValuedLinkedHashMap(listClass);
+    }
+
+    /**
+     * Creates a {@link SetValuedMap} with a {@link LinkedHashMap} as its 
internal
+     * storage
+     *
+     * @param <K> the key type
+     * @param <V> the value type
+     * @return a new <code>SetValuedMap</code>
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <K, V> SetValuedMap<K, V> setValuedLinkedHashMap() {
+        return new SetValuedLinkedHashMap(HashSet.class);
+    }
+
+    /**
+     * Creates a {@link SetValuedMap} with a {@link LinkedHashMap} as its 
internal
+     * storage which maps the keys to a set of type <code>setClass</code>
+     *
+     * @param <K> the key type
+     * @param <V> the value type
+     * @param <C> the Set class type
+     * @param setClass the class of the set
+     * @return a new <code>SetValuedMap</code>
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <K, V, C extends Set<V>> SetValuedMap<K, V> 
setValuedLinkedHashMap(final Class<C> setClass) {
+        return new SetValuedLinkedHashMap(setClass);
+    }
+
+    /**
+     * Creates a MultiValueMap based on a <code>LinkedHashMap</code> with the 
default
+     * initial capacity (16) and the default load factor (0.75), which stores
+     * the multiple values in an <code>LinkedList</code>.
+     */
+    @SuppressWarnings("unchecked")
+    public MultiValuedLinkedHashMap() {
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, LinkedList.class);
+    }
+
+    /**
+     * Creates a MultiValueMap based on a <code>LinkedHashMap</code> with the 
initial
+     * capacity and the default load factor (0.75), which stores the multiple
+     * values in an <code>LinkedList</code>.
+     *
+     * @param initialCapacity the initial capacity of the underlying hash map
+     */
+    @SuppressWarnings("unchecked")
+    public MultiValuedLinkedHashMap(int initialCapacity) {
+        this(initialCapacity, DEFAULT_LOAD_FACTOR, LinkedList.class);
+    }
+
+    /**
+     * Creates a MultiValueMap based on a <code>LinkedHashMap</code> with the 
initial
+     * capacity and the load factor, which stores the multiple values in an
+     * <code>LinkedList</code>.
+     *
+     * @param initialCapacity the initial capacity of the underlying hash map
+     * @param loadFactor the load factor of the underlying hash map
+     */
+    @SuppressWarnings("unchecked")
+    public MultiValuedLinkedHashMap(int initialCapacity, float loadFactor) {
+        this(initialCapacity, loadFactor, LinkedList.class);
+    }
+
+    /**
+     * Creates a MultiValueMap based on a <code>LinkedHashMap</code> with the 
initial
+     * capacity and the load factor, which stores the multiple values in an
+     * <code>LinkedList</code> 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 MultiValuedLinkedHashMap(int initialCapacity, float loadFactor, int 
initialCollectionCapacity) {
+        this(initialCapacity, loadFactor, LinkedList.class, 
initialCollectionCapacity);
+    }
+
+    /**
+     * Creates a MultiValuedLinkedHashMap copying all the mappings of the 
given map.
+     *
+     * @param map a <code>MultiValuedMap</code> to copy into this map
+     */
+    @SuppressWarnings("unchecked")
+    public MultiValuedLinkedHashMap(final MultiValuedMap<? extends K, ? 
extends V> map) {
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, LinkedList.class);
+        super.putAll(map);
+    }
+
+    /**
+     * Creates a MultiValuedLinkedHashMap copying all the mappings of the 
given map.
+     *
+     * @param map a <code>Map</code> to copy into this map
+     */
+    @SuppressWarnings("unchecked")
+    public MultiValuedLinkedHashMap(final Map<? extends K, ? extends V> map) {
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, LinkedList.class);
+        super.putAll(map);
+    }
+
+    /**
+     * Creates a MultiValuedLinkedHashMap which creates the value collections 
using
+     * the supplied <code>collectionClazz</code>.
+     *
+     * @param initialCapacity the initial capacity of the underlying
+     *        <code>LinkedHashMap</code>
+     * @param loadFactor the load factor of the underlying 
<code>LinkedHashMap</code>
+     * @param <C> the collection type
+     * @param collectionClazz the class of the <code>Collection</code> to use 
to
+     *        create the value collections
+     */
+    protected <C extends Collection<V>> MultiValuedLinkedHashMap(int 
initialCapacity, float loadFactor,
+            final Class<C> collectionClazz) {
+        super(new LinkedHashMap<K, Collection<V>>(initialCapacity, 
loadFactor), collectionClazz);
+    }
+
+    /**
+     * Creates a MultiValuedLinkedHashMap which creates the value collections 
using
+     * the supplied <code>collectionClazz</code> and the initial collection
+     * capacity .
+     *
+     * @param initialCapacity the initial capacity of the underlying
+     *        <code>LinkedHashMap</code>
+     * @param loadFactor the load factor of the underlying 
<code>LinkedHashMap</code>
+     * @param initialCollectionCapacity the initial capacity of the
+     *        <code>Collection</code>
+     * @param <C> the collection type
+     * @param collectionClazz the class of the <code>Collection</code> to use 
to
+     *        create the value collections
+     */
+    protected <C extends Collection<V>> MultiValuedLinkedHashMap(int 
initialCapacity, float loadFactor,
+            final Class<C> collectionClazz, int initialCollectionCapacity) {
+        super(new LinkedHashMap<K, Collection<V>>(initialCapacity, 
loadFactor), collectionClazz, initialCollectionCapacity);
+    }
+
+    /** Inner class for ListValuedLinkedMap */
+    private static class ListValuedLinkedHashMap<K, V> extends 
AbstractListValuedMap<K, V> {
+
+        private static final long serialVersionUID = 3667581458573135234L;
+
+        public <C extends List<V>> ListValuedLinkedHashMap(Class<C> listClazz) 
{
+            super(new LinkedHashMap<K, List<V>>(DEFAULT_INITIAL_CAPACITY, 
DEFAULT_LOAD_FACTOR), listClazz);
+        }
+
+        public <C extends List<V>> ListValuedLinkedHashMap(Class<C> listClazz, 
int initialListCapacity) {
+            super(new LinkedHashMap<K, List<V>>(DEFAULT_INITIAL_CAPACITY, 
DEFAULT_LOAD_FACTOR), listClazz,
+                    initialListCapacity);
+        }
+
+    }
+
+    /** Inner class for SetValuedLinkedMap */
+    private static class SetValuedLinkedHashMap<K, V> extends 
AbstractSetValuedMap<K, V> {
+
+        private static final long serialVersionUID = -3817515514829894543L;
+
+        public <C extends Set<V>> SetValuedLinkedHashMap(Class<C> setClazz) {
+            super(new LinkedHashMap<K, Set<V>>(DEFAULT_INITIAL_CAPACITY, 
DEFAULT_LOAD_FACTOR), setClazz);
+        }
+
+        public <C extends Set<V>> SetValuedLinkedHashMap(Class<C> setClazz, 
int initialSetCapacity) {
+            super(new LinkedHashMap<K, Set<V>>(DEFAULT_INITIAL_CAPACITY, 
DEFAULT_LOAD_FACTOR), setClazz,
+                    initialSetCapacity);
+        }
+    }
+
+}

Added: 
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMapTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMapTest.java?rev=1632534&view=auto
==============================================================================
--- 
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMapTest.java
 (added)
+++ 
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/multimap/MultiValuedLinkedHashMapTest.java
 Fri Oct 17 10:51:23 2014
@@ -0,0 +1,230 @@
+/*
+ * 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.*;
+
+import junit.framework.Test;
+
+import org.apache.commons.collections4.*;
+
+/**
+ * Test MultiValuedLinkedHashMap
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public class MultiValuedLinkedHashMapTest<K, V> extends 
AbstractMultiValuedMapTest<K, V> {
+
+    public MultiValuedLinkedHashMapTest(String testName) {
+        super(testName);
+    }
+
+    public static Test suite() {
+        return BulkTest.makeSuite(MultiValuedLinkedHashMapTest.class);
+    }
+
+    @Override
+    public MultiValuedMap<K, V> makeObject() {
+        final MultiValuedMap<K, V> m = new MultiValuedLinkedHashMap<K, V>();
+        return m;
+    }
+
+    public void testIterationOrder() {
+        MultiValuedMap<K, V> map = makeFullMap();
+        MapIterator<K, V> mapIt = map.mapIterator();
+        Iterator keyIt = Arrays.asList(getSampleKeys()).iterator();
+        Iterator valueIt = Arrays.asList(getSampleValues()).iterator();
+
+        while(mapIt.hasNext()) {
+            mapIt.next();
+            assertEquals(mapIt.getKey(), keyIt.next());
+            assertEquals(mapIt.getValue(), valueIt.next());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testSetValuedMapAdd() {
+        final SetValuedMap<K, V> setMap = 
MultiValuedLinkedHashMap.setValuedLinkedHashMap();
+        assertTrue(setMap.get("whatever") instanceof Set);
+
+        Set<V> set = setMap.get("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<K, V> setMap = 
MultiValuedLinkedHashMap.setValuedLinkedHashMap();
+        assertTrue(setMap.get("whatever") instanceof Set);
+
+        Set<V> set = setMap.get("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<K, V> setMap = 
MultiValuedLinkedHashMap.setValuedLinkedHashMap();
+        assertTrue(setMap.get("whatever") instanceof Set);
+
+        Set<V> set = setMap.get("A");
+        set.add((V) "a1");
+        set.add((V) "a2");
+        set.add((V) "a1");
+
+        Iterator<V> it = set.iterator();
+        while (it.hasNext()) {
+            it.next();
+            it.remove();
+        }
+        assertEquals(0, setMap.size());
+        assertFalse(setMap.containsKey("A"));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testListValuedMapAdd() {
+        final ListValuedMap<K, V> listMap = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+        assertTrue(listMap.get("whatever") instanceof List);
+        List<V> list = listMap.get("A");
+        list.add((V) "a1");
+        assertEquals(1, listMap.size());
+        assertTrue(listMap.containsKey("A"));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testListValuedMapAddViaListIterator() {
+        final ListValuedMap<K, V> listMap = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+        ListIterator<V> listIt = listMap.get("B").listIterator();
+        assertFalse(listIt.hasNext());
+        listIt.add((V) "b1");
+        listIt.add((V) "b2");
+        listIt.add((V) "b3");
+        assertEquals(3, listMap.size());
+        assertTrue(listMap.containsKey("B"));
+        // As ListIterator always adds before the current cursor
+        assertFalse(listIt.hasNext());
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testListValuedMapRemove() {
+        final ListValuedMap<K, V> listMap = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+        List<V> list = listMap.get("A");
+        list.add((V) "a1");
+        list.add((V) "a2");
+        list.add((V) "a3");
+        assertEquals(3, listMap.size());
+        assertEquals("a1", list.remove(0));
+        assertEquals(2, listMap.size());
+        assertEquals("a2", list.remove(0));
+        assertEquals(1, listMap.size());
+        assertEquals("a3", list.remove(0));
+        assertEquals(0, listMap.size());
+        assertFalse(listMap.containsKey("A"));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testListValuedMapRemoveViaListIterator() {
+        final ListValuedMap<K, V> listMap = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+        ListIterator<V> listIt = listMap.get("B").listIterator();
+        listIt.add((V) "b1");
+        listIt.add((V) "b2");
+        assertEquals(2, listMap.size());
+        assertTrue(listMap.containsKey("B"));
+        listIt = listMap.get("B").listIterator();
+        while (listIt.hasNext()) {
+            listIt.next();
+            listIt.remove();
+        }
+        assertFalse(listMap.containsKey("B"));
+        listIt.add((V) "b1");
+        listIt.add((V) "b2");
+        assertTrue(listMap.containsKey("B"));
+        assertEquals(2, listMap.get("B").size());
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void testEqualsHashCodeContract() {
+        MultiValuedMap map1 = new MultiValuedLinkedHashMap();
+        MultiValuedMap map2 = new MultiValuedLinkedHashMap();
+
+        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");
+        assertNotSame(map1, map2);
+        assertNotSame(map1.hashCode(), map2.hashCode());
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void testListValuedMapEqualsHashCodeContract() {
+        ListValuedMap map1 = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+        ListValuedMap map2 = 
MultiValuedLinkedHashMap.listValuedLinkedHashMap();
+
+        map1.put("a", "a1");
+        map1.put("a", "a2");
+        map2.put("a", "a1");
+        map2.put("a", "a2");
+        assertEquals(map1, map2);
+        assertEquals(map1.hashCode(), map2.hashCode());
+
+        map1.put("b", "b1");
+        map1.put("b", "b2");
+        map2.put("b", "b2");
+        map2.put("b", "b1");
+        assertNotSame(map1, map2);
+        assertNotSame(map1.hashCode(), map2.hashCode());
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public void testSetValuedMapEqualsHashCodeContract() {
+        SetValuedMap map1 = MultiValuedLinkedHashMap.setValuedLinkedHashMap();
+        SetValuedMap map2 = MultiValuedLinkedHashMap.setValuedLinkedHashMap();
+
+        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());
+    }
+}

Added: 
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.emptyCollection.version4.1.obj
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.emptyCollection.version4.1.obj?rev=1632534&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.emptyCollection.version4.1.obj
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.fullCollection.version4.1.obj
URL: 
http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.fullCollection.version4.1.obj?rev=1632534&view=auto
==============================================================================
Binary file - no diff available.

Propchange: 
commons/proper/collections/trunk/src/test/resources/data/test/MultiValuedLinkedHashMap.fullCollection.version4.1.obj
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream


Reply via email to