diff --git a/src/java/org/apache/commons/collections/HashBidiMap.java b/src/java/org/apache/commons/collections/HashBidiMap.java index d356e4bde..009f8c95a 100755 --- a/src/java/org/apache/commons/collections/HashBidiMap.java +++ b/src/java/org/apache/commons/collections/HashBidiMap.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Attic/HashBidiMap.java,v 1.1 2003/09/23 20:29:34 matth Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Attic/HashBidiMap.java,v 1.2 2003/09/26 23:28:43 matth Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -57,6 +57,7 @@ */ package org.apache.commons.collections; +import java.io.Serializable; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.HashMap; @@ -68,14 +69,14 @@ import java.util.Set; * Default implementation of BidiMap. * * @since Commons Collections 3.0 - * @version $Id: HashBidiMap.java,v 1.1 2003/09/23 20:29:34 matth Exp $ + * @version $Id: HashBidiMap.java,v 1.2 2003/09/26 23:28:43 matth Exp $ * * @author Matthew Hawthorne */ -public class HashBidiMap extends AbstractMap implements BidiMap { +public class HashBidiMap extends AbstractMap implements BidiMap, Serializable { /** - * Delegate map array. The first map contains standards entries, and the + * Delegate map array. The first map contains standard entries, and the * second contains inverses. */ final Map[] maps = new Map[] { new HashMap(), new HashMap()}; @@ -114,31 +115,36 @@ public class HashBidiMap extends AbstractMap implements BidiMap { } public Object put(Object key, Object value) { + // Removes pair from standard map if a previous inverse entry exists + final Object oldValue = maps[1].put(value, key); + if (oldValue != null) { + maps[0].remove(oldValue); + } + final Object obj = maps[0].put(key, value); - maps[1].put(value, key); return obj; } public Set entrySet() { // The entrySet is the root of most Map methods, care must be taken not // to reference instance methods like size() - + // Creates anonymous AbstractSet return new AbstractSet() { - + public Iterator iterator() { // Creates anonymous Iterator return new Iterator() { // Delegate iterator. final Iterator it = maps[0].entrySet().iterator(); - + // Current iterator entry Map.Entry currentEntry; public void remove() { // Removes from standard and inverse Maps. - + // Object must be removed using the iterator or a // ConcurrentModificationException is thrown it.remove(); @@ -168,7 +174,7 @@ public class HashBidiMap extends AbstractMap implements BidiMap { public int size() { return HashBidiMap.this.maps[0].size(); } - + }; // anonymous AbstractSet } // entrySet() @@ -225,8 +231,8 @@ public class HashBidiMap extends AbstractMap implements BidiMap { }; // anonymous Iterator } - }; // anonymous AbstractSet - + }; // anonymous AbstractSet + } // entrySet() } // InverseBidiMap diff --git a/src/test/org/apache/commons/collections/TestBidiMap.java b/src/test/org/apache/commons/collections/TestBidiMap.java index 9feaa9106..d2c872ced 100755 --- a/src/test/org/apache/commons/collections/TestBidiMap.java +++ b/src/test/org/apache/commons/collections/TestBidiMap.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/Attic/TestBidiMap.java,v 1.1 2003/09/23 20:29:34 matth Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/Attic/TestBidiMap.java,v 1.2 2003/09/26 23:28:43 matth Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -59,14 +59,16 @@ package org.apache.commons.collections; import java.util.Map; +import junit.framework.TestCase; + /** * JUnit tests. * * @author Matthew Hawthorne - * @version $Id: TestBidiMap.java,v 1.1 2003/09/23 20:29:34 matth Exp $ + * @version $Id: TestBidiMap.java,v 1.2 2003/09/26 23:28:43 matth Exp $ * @see org.apache.commons.collections.BidiMap */ -public abstract class TestBidiMap extends TestMap { +public abstract class TestBidiMap extends TestCase { // Test data. private static final Object KEY = "key1"; @@ -130,7 +132,36 @@ public abstract class TestBidiMap extends TestMap { inverseMap.getKey(entries[0][0])); } + /** + * Ensures that calling: + * + *
+     * map.add(a, c)
+     * map.add(b, c)
+     * 
+ * + * Removes the entry (a, c) + */ + public void testAddDuplicateValue() { + final BidiMap map = createBidiMap(); + + final Object key1 = "key1"; + final Object key2 = "key2"; + final Object value = "value"; + + map.put(key1, value); + map.put(key2, value); + + assertTrue( + "Key/value pair was not removed on duplicate value.", + !map.containsKey(key1)); + + assertEquals("Key/value mismatch", key2, map.getKey(value)); + } + + // ---------------------------------------------------------------- // Removal tests + // ---------------------------------------------------------------- public void testClear() { BidiMap map = createBidiMapWithData(); @@ -153,7 +184,7 @@ public abstract class TestBidiMap extends TestMap { public void testRemove() { remove(createBidiMapWithData(), KEY); remove(createBidiMapWithData().inverseBidiMap(), VALUE); - + removeKey(createBidiMapWithData(), VALUE); removeKey(createBidiMapWithData().inverseBidiMap(), KEY); } @@ -163,7 +194,7 @@ public abstract class TestBidiMap extends TestMap { assertTrue("Key was not removed.", !map.containsKey(key)); assertNull("Value was not removed.", map.getKey(value)); } - + private final void removeKey(BidiMap map, Object value) { final Object key = map.removeKey(value); assertTrue("Key was not removed.", !map.containsKey(key)); @@ -215,11 +246,15 @@ public abstract class TestBidiMap extends TestMap { // Data generation methods // ---------------------------------------------------------------- + /** + * This classes used to extend collections.TestMap, but can't anymore since + * put() breaks a contract. + */ protected Map makeEmptyMap() { return createBidiMap(); } - private final BidiMap createBidiMapWithData() { + protected final BidiMap createBidiMapWithData() { final BidiMap map = createBidiMap(); fillMap(map); return map;