While I agree with the theory of having a MapEntry impl that is more final than at present, I can't support changing the current implementation as it is backwards incompatible.
So, I have created a pairs subdirectory and put some classes in there based on your code. There are no tests ATM. See what you think. If you reckon its OK perhaps you could tweak your tests to work with the new package, and we could then deprecate the old DefaultMapEntry. Stephen ----- Original Message ----- From: "Neil O'Toole" <[EMAIL PROTECTED]> To: "Jakarta Commons Developers List" <[EMAIL PROTECTED]> Sent: Thursday, September 25, 2003 6:27 AM Subject: Re: [collections] Map.Entry and KeyValue > >From my earlier posts: > > 1. >> Although one (including my good self!) might initially think that > a key-value class and a Map.Entry class are interchangeable, this is > not > in fact the case. DefaultMapEntry is not suitable for use as a general > purpose KeyValue class, as it is effectively non-extendable... [due to > #equals and #hashCode being defined by Map.Entry API doc] > > 2. >> My suggested solution is to add a class [KeyValuePair.java] > containing the code from DefaultMapEntry, but not implementing > Map.Entry. DefaultMapEntry can then subclass [KeyValuePair] and > implement Map.Entry > > > I actually missed the big reason why KeyValuePair and Map.Entry are not > interchangeable. A Map.Entry's key is an invariant, while a > KeyValuePair's key is mutable. The key-invariant property means that > the existing DefaultMapEntry implementation is in fact broken - the > #setKey method should not be present. Note that the Map.Entry impls in > java.util do not feature a key mutator (and of course - far more > importantly - the Map.Entry interface itself does not). > > It follows that my suggested solution from (1) above is bogus, as > KeyValuePair has a #setKey method which DefaultMapEntry would inherit. > To retain the key-invariant property, DefaultMapEntry would have to > override #setKey to either (a) silently do nothing, or (b) throw an > UnsupportedOperationException or such; - both horrible options. > Moreover, since the suggested hierarchial relationship between the two > classes was based on a faulty understanding of their similarity, it's > best to ditch that relationship and have the two classes stand alone. > > I've attached implementations/patches to that effect. However, all is > not entirely lost ;) as KeyValuePair has a constructor that takes a > Map.Entry and also has a #toMapEntry method, thus retaining a bridge > between the two classes. > > > I'm happy to add it....with a test case :-) > > Stephen > > Test class for KeyValuePair attached. Also included is a test class for > DefaultMapEntry (TestMapEntry.java) as it does not appear to have one > (or am I somehow missing it?); also a patch for TestAll to include the > new test classes. > > - Neil > > > > ---------------------------------------------------------------------------- ---- > /* > * $Header: /home/cvspublic/jakarta-commons/collections/src/java/org/apache/commons/coll ections/DefaultMapEntry.java,v 1.11 2003/08/31 17:26:43 scolebourne Exp $ > * ==================================================================== > * > * The Apache Software License, Version 1.1 > * > * Copyright (c) 2001-2003 The Apache Software Foundation. All rights > * reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * > * 3. The end-user documentation included with the redistribution, if > * any, must include the following acknowledgement: > * "This product includes software developed by the > * Apache Software Foundation (http://www.apache.org/)." > * Alternately, this acknowledgement may appear in the software itself, > * if and wherever such third-party acknowledgements normally appear. > * > * 4. The names "The Jakarta Project", "Commons", and "Apache Software > * Foundation" must not be used to endorse or promote products derived > * from this software without prior written permission. For written > * permission, please contact [EMAIL PROTECTED] > * > * 5. Products derived from this software may not be called "Apache" > * nor may "Apache" appear in their names without prior written > * permission of the Apache Software Foundation. > * > * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED > * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR > * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * ==================================================================== > * > * This software consists of voluntary contributions made by many > * individuals on behalf of the Apache Software Foundation. For more > * information on the Apache Software Foundation, please see > * <http://www.apache.org/>. > * > */ > package org.apache.commons.collections; > > import java.util.Map; > > /** > * A mutable key-value pair. Note that a <code>KeyValuePair</code> instance > * may not contain itself as a key or value. > * > * @since Commons Collections 3.0 > * @version $Revision: $ > * > * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> > * @author <a href="mailto:[EMAIL PROTECTED]">Michael A. Smith</a> > * @author Neil O'Toole > */ > public class KeyValuePair > { > > /** The key */ > private Object key; > /** The value */ > private Object value; > > /** > * Constructs a new <Code>KeyValuePair</Code> with a null key > * and null value. > */ > public KeyValuePair() > { > } > > /** > * Constructs a new <Code>KeyValuePair</Code> with the given > * key and given value. > * > * @param key the key for the entry, may be null > * @param value the value for the entry, may be null > */ > public KeyValuePair(Object key, Object value) > { > this.key = key; > this.value = value; > } > > /** > * Copy constructor. > */ > public KeyValuePair(KeyValuePair copy) > { > this.key = copy.getKey(); > this.value = copy.getValue(); > } > > /** > * Constructs a new <Code>KeyValuePair</Code> with key > * and value from the supplied <code>Map.Entry</code>. > */ > public KeyValuePair(Map.Entry entry) > { > this.key = entry.getKey(); > this.value = entry.getValue(); > } > > /** > * Returns true if the compared object is also a <code>KeyValuePair</code>, > * and its key and value are equal to this object's key and value. > */ > public boolean equals(Object o) > { > if (o == this) > { > return true; > } > > if (o instanceof KeyValuePair == false) > { > return false; > } > > KeyValuePair kv2 = (KeyValuePair) o; > > return ( > (getKey() == null ? kv2.getKey() == null : getKey().equals(kv2.getKey())) > && (getValue() == null ? kv2.getValue() == null : getValue().equals(kv2.getValue()))); > } > > /** > * Generates hashcode as per [EMAIL PROTECTED] Map.Entry#hashCode}, but note that > * subclasses may override this method to provide a more appropriate hash. > * > * @return a hash generated as per the Map.Entry#hashCode javadoc. > */ > public int hashCode() > { > return ((getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode())); > } > > /** > * Returns the key. > * > * @return the key > */ > public Object getKey() > { > return key; > } > > /** > * Returns the value. > * > * @return the value > */ > public Object getValue() > { > return value; > } > > /** > * Sets the key. > * > * @param key the new key > * @return the old key > * @throws IllegalArgumentException if key is this object > */ > public Object setKey(Object key) > { > if (key == this) > { > throw new IllegalArgumentException("A KeyValuePair may not contain itself as a key."); > } > > final Object old = this.key; > this.key = key; > return old; > } > > /** > * Sets the value. > * > * @return the old value of the value > * @param value the new value > * @throws IllegalArgumentException if value is this object > */ > public Object setValue(Object value) > { > if (value == this) > { > throw new IllegalArgumentException("A KeyValuePair may not contain itself as a value."); > } > > final Object old = this.value; > this.value = value; > return old; > } > > /** > * Returns a new <code>Map.Entry</code> object with key and value from this <code>KeyValuePair</code>. > */ > public Map.Entry toMapEntry() > { > return new DefaultMapEntry(this.getKey(), this.getValue()); > } > > public String toString() > { > return new StringBuffer().append(getKey()).append('=').append(getValue()).toString(); > } > > } > ---------------------------------------------------------------------------- ---- > Index: DefaultMapEntry.java > =================================================================== > RCS file: /home/cvspublic/jakarta-commons/collections/src/java/org/apache/commons/coll ections/DefaultMapEntry.java,v > retrieving revision 1.11 > diff -u -r1.11 DefaultMapEntry.java > --- DefaultMapEntry.java 31 Aug 2003 17:26:43 -0000 1.11 > +++ DefaultMapEntry.java 25 Sep 2003 05:14:06 -0000 > @@ -60,18 +60,26 @@ > import java.util.Map; > > /** > - * A default implementation of [EMAIL PROTECTED] java.util.Map.Entry} > + * A default implementation of [EMAIL PROTECTED] java.util.Map.Entry}. A > + * <code>Map.Entry</code>'s key cannot be changed, and thus > + * the key-related fields and methods are final. > + * > + * Additionally, note that the <code>#equals</code> > + * and <code>#hashCode</code> methods are implemented as specified by > + * the <code>Map.Entry</code> API doc, and > + * thus these methods are also declared final. > * > * @since Commons Collections 1.0 > * @version $Revision: 1.11 $ $Date: 2003/08/31 17:26:43 $ > * > * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> > * @author <a href="mailto:[EMAIL PROTECTED]">Michael A. Smith</a> > + * @author Neil O'Toole > */ > public class DefaultMapEntry implements Map.Entry { > > /** The key */ > - private Object key; > + private final Object key; > /** The value */ > private Object value; > > @@ -80,6 +88,7 @@ > * and null value. > */ > public DefaultMapEntry() { > + this.key = null; > } > > /** > @@ -93,13 +102,23 @@ > this.key = key; > this.value = value; > } > + > + > + /** > + * Copy constructor - creates a new <Code>DefaultMapEntry</Code> with > + * key and value from the supplied Map.Entry. > + * > + */ > + public DefaultMapEntry(Map.Entry copy) { > + this.key = copy.getKey(); > + this.value = copy.getValue(); > + } > > /** > * Implemented per API documentation of > * [EMAIL PROTECTED] java.util.Map.Entry#equals(Object)} > */ > - public boolean equals(Object o) { > - if( o == null ) return false; > + public final boolean equals(Object o) { > if( o == this ) return true; > > if ( ! (o instanceof Map.Entry ) ) > @@ -116,22 +135,18 @@ > * Implemented per API documentation of > * [EMAIL PROTECTED] java.util.Map.Entry#hashCode()} > */ > - public int hashCode() { > + public final int hashCode() { > return ( ( getKey() == null ? 0 : getKey().hashCode() ) ^ > ( getValue() == null ? 0 : getValue().hashCode() ) ); > } > > > - > - // Map.Entry interface > - //------------------------------------------------------------------------- > - > /** > * Returns the key. > * > * @return the key > */ > - public Object getKey() { > + public final Object getKey() { > return key; > } > > @@ -144,29 +159,29 @@ > return value; > } > > - // Properties > - //------------------------------------------------------------------------- > > - /** > - * Sets the key. This method does not modify any map. > - * > - * @param key the new key > - */ > - public void setKey(Object key) { > - this.key = key; > - } > - > /** > * Note that this method only sets the local reference inside this object and > - * does not modify the original Map. > + * does not modify any Map. > * > * @return the old value of the value > * @param value the new value > + * @throws IllegalArgumentException if value is this object. A Map.Entry may not contain > + * itself as a value because Map.Entry's required #hashCode implementation will > + * enter an infinite recursion. > */ > public Object setValue(Object value) { > + if (value == this) > + throw new IllegalArgumentException("A Map.Entry may not contain itself as a value."); > + > Object answer = this.value; > this.value = value; > return answer; > } > + > + public String toString() > + { > + return new StringBuffer().append(key).append('=').append(value).toString(); > + } > > } > ---------------------------------------------------------------------------- ---- > Index: TestAll.java > =================================================================== > RCS file: /home/cvspublic/jakarta-commons/collections/src/test/org/apache/commons/coll ections/TestAll.java,v > retrieving revision 1.47 > diff -u -r1.47 TestAll.java > --- TestAll.java 20 Sep 2003 16:58:19 -0000 1.47 > +++ TestAll.java 25 Sep 2003 05:12:58 -0000 > @@ -105,7 +105,9 @@ > suite.addTest(TestFastTreeMap1.suite()); > suite.addTest(TestHashBag.suite()); > suite.addTest(TestIteratorUtils.suite()); > + suite.addTest(TestKeyValuePair.suite()); > suite.addTest(TestLRUMap.suite()); > + suite.addTest(TestMapEntry.suite()); > suite.addTest(TestMultiHashMap.suite()); > suite.addTest(TestMultiKey.suite()); > suite.addTest(TestNodeCachingLinkedList.suite()); > ---------------------------------------------------------------------------- ---- > /* > * $Header: x:/apps/cvsnt/cvs_repository/main/notifyingcollections/src/test/org/apache/c ommons/collections/TestKeyValueRecord.java,v 1.1 2003/09/20 22:00:46 otoolen Exp $ > * ==================================================================== > * > * The Apache Software License, Version 1.1 > * > * Copyright (c) 2001-2003 The Apache Software Foundation. All rights > * reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * > * 3. The end-user documentation included with the redistribution, if > * any, must include the following acknowledgment: > * "This product includes software developed by the > * Apache Software Foundation (http://www.apache.org/)." > * Alternately, this acknowledgment may appear in the software itself, > * if and wherever such third-party acknowledgments normally appear. > * > * 4. The names "The Jakarta Project", "Commons", and "Apache Software > * Foundation" must not be used to endorse or promote products derived > * from this software without prior written permission. For written > * permission, please contact [EMAIL PROTECTED] > * > * 5. Products derived from this software may not be called "Apache" > * nor may "Apache" appear in their names without prior written > * permission of the Apache Software Foundation. > * > * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED > * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR > * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * ==================================================================== > * > * This software consists of voluntary contributions made by many > * individuals on behalf of the Apache Software Foundation. For more > * information on the Apache Software Foundation, please see > * <http://www.apache.org/>. > * > */ > package org.apache.commons.collections; > > import java.util.HashMap; > import java.util.Map; > > import junit.framework.Test; > import junit.framework.TestCase; > import junit.framework.TestSuite; > > /** > * > * @author Neil O'Toole > */ > public class TestKeyValuePair extends TestCase > { > private final String key = "name"; > private final String value = "duke"; > > > public TestKeyValuePair(String testName) > { > super(testName); > > } > > public static void main(String[] args) > { > junit.textui.TestRunner.run(TestKeyValuePair.class); > } > > > public static Test suite() > { > return new TestSuite(TestKeyValuePair.class); > } > > > public void testAccessorsAndMutators() > { > KeyValuePair kv = new KeyValuePair(); > > kv.setKey(key); > assertTrue(kv.getKey() == key); > > kv.setValue(value); > assertTrue(kv.getValue() == value); > > // check that null doesn't do anything funny > kv.setKey(null); > assertTrue(kv.getKey() == null); > > kv.setValue(null); > assertTrue(kv.getValue() == null); > > } > > public void testSelfReferenceHandling() > { > // test that #setKey and #setValue do not permit > // the KVP to contain itself (and thus cause infinite recursion > // in #hashCode and #toString) > > KeyValuePair kv = new KeyValuePair(); > > try > { > kv.setKey(kv); > fail("Should throw an IllegalArgumentException"); > } > catch(IllegalArgumentException iae) > { > // expected to happen... > > // check that the KVP's state has not changed > assertTrue(kv.getKey() == null && kv.getValue() == null); > } > > try > { > kv.setValue(kv); > fail("Should throw an IllegalArgumentException"); > } > catch(IllegalArgumentException iae) > { > // expected to happen... > > // check that the KVP's state has not changed > assertTrue(kv.getKey() == null && kv.getValue() == null); > } > } > > > public void testConstructors() > { > // 1. test default constructor > KeyValuePair kv = new KeyValuePair(); > assertTrue(kv.getKey() == null && kv.getValue() == null); > > > // 2. test key-value constructor > kv = new KeyValuePair(key, value); > assertTrue(kv.getKey() == key && kv.getValue() == value); > > > // 3. test copy constructor > KeyValuePair kv2 = new KeyValuePair(kv); > assertTrue(kv2.getKey() == key && kv2.getValue() == value); > > // test that the KVPs are independent > kv.setKey(null); > kv.setValue(null); > > assertTrue(kv2.getKey() == key && kv2.getValue() == value); > > > > // 4. test Map.Entry constructor > Map map = new HashMap(); > map.put(key, value); > Map.Entry entry = (Map.Entry) map.entrySet().iterator().next(); > > kv = new KeyValuePair(entry); > assertTrue(kv.getKey() == key && kv.getValue() == value); > > // test that the KVP is independent of the Map.Entry > entry.setValue(null); > assertTrue(kv.getValue() == value); > > } > > public void testEqualsAndHashCode() > { > // 1. test with object data > KeyValuePair kv = new KeyValuePair(key, value); > KeyValuePair kv2 = new KeyValuePair(key, value); > > assertTrue(kv.equals(kv)); > assertTrue(kv.equals(kv2)); > assertTrue(kv.hashCode() == kv2.hashCode()); > > // 2. test with nulls > kv = new KeyValuePair(); > kv2 = new KeyValuePair(); > > assertTrue(kv.equals(kv)); > assertTrue(kv.equals(kv2)); > assertTrue(kv.hashCode() == kv2.hashCode()); > } > > public void testToString() > { > KeyValuePair kv = new KeyValuePair(key, value); > assertTrue(kv.toString().equals(kv.getKey() + "=" + kv.getValue())); > > // test with nulls > kv = new KeyValuePair(); > assertTrue(kv.toString().equals(kv.getKey() + "=" + kv.getValue())); > } > > > public void testToMapEntry() > { > KeyValuePair kv = new KeyValuePair(key, value); > > Map map = new HashMap(); > map.put(kv.getKey(), kv.getValue()); > Map.Entry entry = (Map.Entry) map.entrySet().iterator().next(); > > assertTrue(entry.equals(kv.toMapEntry())); > assertTrue(entry.hashCode() == kv.hashCode()); > } > > } > ---------------------------------------------------------------------------- ---- > /* > * $Header: x:/apps/cvsnt/cvs_repository/main/notifyingcollections/src/test/org/apache/c ommons/collections/TestKeyValueRecord.java,v 1.1 2003/09/20 22:00:46 otoolen Exp $ > * ==================================================================== > * > * The Apache Software License, Version 1.1 > * > * Copyright (c) 2001-2003 The Apache Software Foundation. All rights > * reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions > * are met: > * > * 1. Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > * > * 2. Redistributions in binary form must reproduce the above copyright > * notice, this list of conditions and the following disclaimer in > * the documentation and/or other materials provided with the > * distribution. > * > * 3. The end-user documentation included with the redistribution, if > * any, must include the following acknowledgment: > * "This product includes software developed by the > * Apache Software Foundation (http://www.apache.org/)." > * Alternately, this acknowledgment may appear in the software itself, > * if and wherever such third-party acknowledgments normally appear. > * > * 4. The names "The Jakarta Project", "Commons", and "Apache Software > * Foundation" must not be used to endorse or promote products derived > * from this software without prior written permission. For written > * permission, please contact [EMAIL PROTECTED] > * > * 5. Products derived from this software may not be called "Apache" > * nor may "Apache" appear in their names without prior written > * permission of the Apache Software Foundation. > * > * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED > * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR > * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, > * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT > * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > * SUCH DAMAGE. > * ==================================================================== > * > * This software consists of voluntary contributions made by many > * individuals on behalf of the Apache Software Foundation. For more > * information on the Apache Software Foundation, please see > * <http://www.apache.org/>. > * > */ > package org.apache.commons.collections; > > import java.util.HashMap; > import java.util.Map; > > import junit.framework.Test; > import junit.framework.TestCase; > import junit.framework.TestSuite; > > /** > * > * @author Neil O'Toole > */ > public class TestMapEntry extends TestCase > { > private final String key = "name"; > private final String value = "duke"; > > > public TestMapEntry(String testName) > { > super(testName); > > } > > public static void main(String[] args) > { > junit.textui.TestRunner.run(TestMapEntry.class); > } > > public static Test suite() > { > return new TestSuite(TestMapEntry.class); > } > > /** > * Make an instance of Map.Entry with the default (null) key and value. > * Subclasses should override this method to return a Map.Entry > * of the type being tested. > */ > public Map.Entry makeMapEntry() > { > return new DefaultMapEntry(); > } > > /** > * Make an instance of Map.Entry with the specified key and value. > * Subclasses should override this method to return a Map.Entry > * of the type being tested. > */ > public Map.Entry makeMapEntry(Object key, Object value) > { > return new DefaultMapEntry(key, value); > } > > > > public Map.Entry makeKnownMapEntry() > { > return makeKnownMapEntry(null, null); > } > > > public Map.Entry makeKnownMapEntry(Object key, Object value) > { > Map map = new HashMap(1); > map.put(key, value); > Map.Entry entry = (Map.Entry) map.entrySet().iterator().next(); > return entry; > } > > > public void testAccessorsAndMutators() > { > Map.Entry entry = makeMapEntry(key, value); > > > assertTrue(entry.getKey() == key); > > entry.setValue(value); > assertTrue(entry.getValue() == value); > > // check that null doesn't do anything funny > entry = makeMapEntry(null, null); > assertTrue(entry.getKey() == null); > > entry.setValue(null); > assertTrue(entry.getValue() == null); > } > > > public void testSelfReferenceHandling() > { > // test that #setValue does not permit > // the MapEntry to contain itself (and thus cause infinite recursion > // in #hashCode and #toString) > > Map.Entry entry = makeMapEntry(); > > try > { > entry.setValue(entry); > fail("Should throw an IllegalArgumentException"); > } > catch(IllegalArgumentException iae) > { > // expected to happen... > > // check that the KVP's state has not changed > assertTrue(entry.getKey() == null && entry.getValue() == null); > } > } > > > /** > * Subclasses should override this method. > * > */ > public void testConstructors() > { > // 1. test default constructor > Map.Entry entry = new DefaultMapEntry(); > assertTrue(entry.getKey() == null && entry.getValue() == null); > > > // 2. test key-value constructor > entry = new DefaultMapEntry(key, value); > assertTrue(entry.getKey() == key && entry.getValue() == value); > > > // 3. test copy constructor > Map.Entry entry2 = new DefaultMapEntry(entry); > assertTrue(entry2.getKey() == key && entry2.getValue() == value); > > // test that the objects are independent > entry.setValue(null); > > assertTrue(entry2.getValue() == value); > } > > public void testEqualsAndHashCode() > { > // 1. test with object data > Map.Entry e1 = makeMapEntry(key, value); > Map.Entry e2 = makeKnownMapEntry(key, value); > > assertTrue(e1.equals(e1)); > assertTrue(e2.equals(e1)); > assertTrue(e1.hashCode() == e2.hashCode()); > > // 2. test with nulls > e1 = makeMapEntry(); > e2 = makeKnownMapEntry(); > > assertTrue(e1.equals(e1)); > assertTrue(e2.equals(e1)); > assertTrue(e1.hashCode() == e2.hashCode()); > } > > public void testToString() > { > Map.Entry entry = makeMapEntry(key, value); > assertTrue(entry.toString().equals(entry.getKey() + "=" + entry.getValue())); > > // test with nulls > entry = makeMapEntry(); > assertTrue(entry.toString().equals(entry.getKey() + "=" + entry.getValue())); > } > > > } > > ---------------------------------------------------------------------------- ---- > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
