Updated logic in put() to remove pair on duplicate value. Because of this, TestBidiMap can no longer extend TestMap since this seems to break the Map contract.

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131193 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Matthew Hawthorne 2003-09-26 23:28:43 +00:00
parent 43c1bd31e8
commit 04c90229bb
2 changed files with 59 additions and 18 deletions

View File

@ -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 * The Apache Software License, Version 1.1
@ -57,6 +57,7 @@
*/ */
package org.apache.commons.collections; package org.apache.commons.collections;
import java.io.Serializable;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.AbstractSet; import java.util.AbstractSet;
import java.util.HashMap; import java.util.HashMap;
@ -68,14 +69,14 @@ import java.util.Set;
* Default implementation of <code>BidiMap</code>. * Default implementation of <code>BidiMap</code>.
* *
* @since Commons Collections 3.0 * @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 * @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. * second contains inverses.
*/ */
final Map[] maps = new Map[] { new HashMap(), new HashMap()}; 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) { 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); final Object obj = maps[0].put(key, value);
maps[1].put(value, key);
return obj; return obj;
} }
public Set entrySet() { public Set entrySet() {
// The entrySet is the root of most Map methods, care must be taken not // The entrySet is the root of most Map methods, care must be taken not
// to reference instance methods like size() // to reference instance methods like size()
// Creates anonymous AbstractSet // Creates anonymous AbstractSet
return new AbstractSet() { return new AbstractSet() {
public Iterator iterator() { public Iterator iterator() {
// Creates anonymous Iterator // Creates anonymous Iterator
return new Iterator() { return new Iterator() {
// Delegate iterator. // Delegate iterator.
final Iterator it = maps[0].entrySet().iterator(); final Iterator it = maps[0].entrySet().iterator();
// Current iterator entry // Current iterator entry
Map.Entry currentEntry; Map.Entry currentEntry;
public void remove() { public void remove() {
// Removes from standard and inverse Maps. // Removes from standard and inverse Maps.
// Object must be removed using the iterator or a // Object must be removed using the iterator or a
// ConcurrentModificationException is thrown // ConcurrentModificationException is thrown
it.remove(); it.remove();
@ -168,7 +174,7 @@ public class HashBidiMap extends AbstractMap implements BidiMap {
public int size() { public int size() {
return HashBidiMap.this.maps[0].size(); return HashBidiMap.this.maps[0].size();
} }
}; // anonymous AbstractSet }; // anonymous AbstractSet
} // entrySet() } // entrySet()
@ -225,8 +231,8 @@ public class HashBidiMap extends AbstractMap implements BidiMap {
}; // anonymous Iterator }; // anonymous Iterator
} }
}; // anonymous AbstractSet }; // anonymous AbstractSet
} // entrySet() } // entrySet()
} // InverseBidiMap } // InverseBidiMap

View File

@ -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 * The Apache Software License, Version 1.1
@ -59,14 +59,16 @@ package org.apache.commons.collections;
import java.util.Map; import java.util.Map;
import junit.framework.TestCase;
/** /**
* JUnit tests. * JUnit tests.
* *
* @author Matthew Hawthorne * @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 * @see org.apache.commons.collections.BidiMap
*/ */
public abstract class TestBidiMap extends TestMap { public abstract class TestBidiMap extends TestCase {
// Test data. // Test data.
private static final Object KEY = "key1"; private static final Object KEY = "key1";
@ -130,7 +132,36 @@ public abstract class TestBidiMap extends TestMap {
inverseMap.getKey(entries[0][0])); inverseMap.getKey(entries[0][0]));
} }
/**
* Ensures that calling:
*
* <pre>
* map.add(a, c)
* map.add(b, c)
* </pre>
*
* 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 // Removal tests
// ----------------------------------------------------------------
public void testClear() { public void testClear() {
BidiMap map = createBidiMapWithData(); BidiMap map = createBidiMapWithData();
@ -153,7 +184,7 @@ public abstract class TestBidiMap extends TestMap {
public void testRemove() { public void testRemove() {
remove(createBidiMapWithData(), KEY); remove(createBidiMapWithData(), KEY);
remove(createBidiMapWithData().inverseBidiMap(), VALUE); remove(createBidiMapWithData().inverseBidiMap(), VALUE);
removeKey(createBidiMapWithData(), VALUE); removeKey(createBidiMapWithData(), VALUE);
removeKey(createBidiMapWithData().inverseBidiMap(), KEY); removeKey(createBidiMapWithData().inverseBidiMap(), KEY);
} }
@ -163,7 +194,7 @@ public abstract class TestBidiMap extends TestMap {
assertTrue("Key was not removed.", !map.containsKey(key)); assertTrue("Key was not removed.", !map.containsKey(key));
assertNull("Value was not removed.", map.getKey(value)); assertNull("Value was not removed.", map.getKey(value));
} }
private final void removeKey(BidiMap map, Object value) { private final void removeKey(BidiMap map, Object value) {
final Object key = map.removeKey(value); final Object key = map.removeKey(value);
assertTrue("Key was not removed.", !map.containsKey(key)); assertTrue("Key was not removed.", !map.containsKey(key));
@ -215,11 +246,15 @@ public abstract class TestBidiMap extends TestMap {
// Data generation methods // Data generation methods
// ---------------------------------------------------------------- // ----------------------------------------------------------------
/**
* This classes used to extend collections.TestMap, but can't anymore since
* put() breaks a contract.
*/
protected Map makeEmptyMap() { protected Map makeEmptyMap() {
return createBidiMap(); return createBidiMap();
} }
private final BidiMap createBidiMapWithData() { protected final BidiMap createBidiMapWithData() {
final BidiMap map = createBidiMap(); final BidiMap map = createBidiMap();
fillMap(map); fillMap(map);
return map; return map;