commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Stephen Colebourne" <scolebou...@btopenworld.com>
Subject Re: [collections] submission: KeyValueRecord
Date Sat, 20 Sep 2003 23:21:52 GMT
'Record' confused me and made me think of databases. Is KeyValueHistory a
better name?

DefaultMapEntry IIRC is the simple Map.Entry impl.
Stephen

PS. I guess this came from the rich events package, which I would like to
see as an implementation of the observed code.

----- Original Message -----
From: "Neil O'Toole" <neilotoole@users.sourceforge.net>
To: <commons-dev@jakarta.apache.org>
Sent: Saturday, September 20, 2003 11:06 PM
Subject: [collections] submission: KeyValueRecord


> Attached is source (& associated tests) for KeyValueRecord.java.
> KeyValueRecord is an immutable {key, value, previous-value} triplet, a
> simple but very useful data structure. It's particularly of use with
> Map (and Map.Entry) for storing, tracking, and comparing entry state,
> but can obviously be used for any key-value data. The constructors
> include one to create a KeyValueRecord from a Map.Entry. There is also
> a method to view the KeyValueRecord as a Map.Entry (#asMapEntry). See
> the javadoc for more details.
>
> ** I had a swift look through [collections] and [lang], and didn't see
> a simple KeyValuePair implementation... Have I missed this somewhere?
> If not, I have an implementation which I will post.
>
> Thanks,
>
> Neil
>


----------------------------------------------------------------------------
----


> /*
>  * $Header:
x:/apps/cvsnt/cvs_repository/main/notifyingcollections/src/java/org/apache/c
ommons/collections/KeyValueRecord.java,v 1.2 2003/09/20 22:00:32 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 apache@apache.org.
>  *
>  * 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;
>
> /**
>  * An immutable {key, value, previous-value} triplet. This class is
frequently used
>  * in conjunction with <code>Map.Entry</code>. A constructor is provided
to create
>  * a <code>KeyValueRecord</code> from a <code>Map.Entry</code>,
and the
{@link #asMapEntry}
>  * method can be used to view an object of this class as a
<code>Map.Entry</code>.
>  * Note that it is not possible for <code>KeyValueRecord</code> to
implement the <code>Map.Entry</code>
>  * interface as the <code>#equals</code> implementations are not
compatible.
>  *
>  *
>  *
>  * @author Neil O'Toole
>  */
>
> public class KeyValueRecord
> {
> private static final Object NO_PREVIOUS_VALUE = new Object();
>
> private int hash = -1; // lazily calculated
>
> private final Object key;
> private final Object previous;
> private final Object value;
>
> /**
> * Create a new <code>KeyValueRecord</code> with key and value from the
supplied
> * <code>Map.Entry</code> and no previous value.
> */
> public KeyValueRecord(final Map.Entry entry)
> {
> this(entry.getKey(), entry.getValue(), NO_PREVIOUS_VALUE);
> }
>
> /**
> * Create a new <code>KeyValueRecord</code> with the specified key and
value and
> * no previous value.
> */
> public KeyValueRecord(final Object key, final Object value)
> {
> this(key, value, NO_PREVIOUS_VALUE);
> }
>
> /**
> * Create a new <code>KeyValueRecord</code> with the specified key, value,
and previous value.
> */
> public KeyValueRecord(final Object key, final Object value, final Object
previousValue)
> {
> this.key = key;
> this.value = value;
> this.previous = previousValue;
> }
>
> /**
> * Returns a {@link Map.Entry} view of the supplied
<code>KeyValueRecord</code>. The
> * returned entry is unmodifiable (<code>#setValue</code> throws an {@link
UnsupportedOperationException}),
> * as the backing <code>KeyValueRecord</code> is itself immutable.
> * The returned entry correctly implements the <code>#hashCode</code> and
> * <code>#equals</code> operations as per the <code>Map.Entry</code>
contract.
> */
>
> public Map.Entry asMapEntry()
> {
> return new Map.Entry()
> {
> private int hash = -1;
>
> public boolean equals(Object o)
> {
> if (o instanceof Map.Entry == false)
> {
> return false;
> }
>
> if (o == this)
> {
> return true;
> }
>
> Map.Entry e = (Map.Entry) o;
>
> return (
> KeyValueRecord.this.getKey() == null
> ? e.getKey() == null
> : KeyValueRecord.this.getKey().equals(e.getKey()))
> && (KeyValueRecord.this.getValue() == null
> ? e.getValue() == null
> : KeyValueRecord.this.getValue().equals(e.getValue()));
> }
>
> public Object getKey()
> {
> return KeyValueRecord.this.getKey();
> }
>
> public Object getValue()
> {
> return KeyValueRecord.this.getValue();
> }
>
> public int hashCode()
> {
> if (this.hash == -1)
> {
> this.hash =
> (KeyValueRecord.this.getKey() == null ? 0 :
KeyValueRecord.this.getKey().hashCode())
> ^ (KeyValueRecord.this.getValue() == null ? 0 :
KeyValueRecord.this.getValue().hashCode());
> }
>
> return this.hash;
> }
>
> public Object setValue(Object value)
> {
> throw new UnsupportedOperationException("This Map.Entry is
unmodifiable.");
> }
>
> public String toString()
> {
> return new StringBuffer()
> .append(KeyValueRecord.this.getKey())
> .append('=')
> .append(KeyValueRecord.this.getValue())
> .toString();
> }
> };
>
> }
>
> /**
> * Compares the specified object with this <code>KeyValueRecord</code> for
equality. Returns
> * true if the given object is also a <code>KeyValueRecord</code> and
> * the records' key, value, and previous value are equal.
> *
> * @param o object to be compared for equality with this
<code>KeyValueRecord</code>.
> * @return <code>true</code> if the specified object is equal to this
> *         record.
> */
> public boolean equals(final Object o)
> {
> if (!(o instanceof KeyValueRecord))
> {
> return false;
> }
>
> if (this == o)
> {
> return true;
> }
>
> final KeyValueRecord kvr = (KeyValueRecord) o;
>
> return (this.key == null ? kvr.key == null : this.key.equals(kvr.key))
> && (this.value == null ? kvr.value == null : this.value.equals(kvr.value))
> && (this.previous == NO_PREVIOUS_VALUE
> ? (kvr.previous == NO_PREVIOUS_VALUE)
> : (this.previous == null ? kvr.previous == null :
this.previous.equals(kvr.previous)));
> }
>
> /**
> * Returns the key associated with this record.
> */
> public Object getKey()
> {
> return this.key;
> }
>
> /**
> * Returns the value previously associated with this record's key, if any.
Note that
> * <code>null</code> will be returned
> * if the previous value is <code>null</code> <i>or</i> if there
is no
previous value.
> * Therefore {@link #hasPreviousValue()} should be used to test if there is
a previous value.
> *
> * @return the previous value (which may be <code>null</code>)
> * associated with this record's key, or <code>null</code> if there is no
> * previous value.
> */
> public Object getPreviousValue()
> {
> return (this.previous == NO_PREVIOUS_VALUE) ? null : this.previous;
> }
>
> /**
> * Returns the value associated with this record's key.
> *
> * @return the object (which may be <code>null</code>)
> * associated with this record's key
> */
> public Object getValue()
> {
> return this.value;
> }
>
> public int hashCode()
> {
> if (this.hash == -1)
> {
> this.hash =
> (this.key == null ? 0 : this.key.hashCode())
> ^ (this.value == null ? 0 : this.value.hashCode())
> ^ (this.previous == null ? 0 : this.previous.hashCode());
> }
>
> return this.hash;
> }
>
> /**
> * Returns true if this record's key
> * was associated with a value previous to being
> * associated with its current value.
> *
> * @return <code>true</code> if this key previously had a value associated
> * with it, <code>false</code> otherwise.
> * @see #getPreviousValue()
> */
> public boolean hasPreviousValue()
> {
> return this.previous != NO_PREVIOUS_VALUE;
> }
>
> /**
> * Returns a string representation of this <code>KeyValueRecord</code>. The
text
> * rendering is <code>key=value</code> or <code>key=value (previous)</code>
> * depending on whether this <code>KeyValueRecord</code>
> * has a previous value.
> *
> */
> public String toString()
> {
> final StringBuffer sb = new
StringBuffer().append(this.key).append('=').append(this.value);
>
> if (this.hasPreviousValue())
> {
> sb.append(' ').append('(').append(this.getPreviousValue()).append(')');
> }
>
> return sb.toString();
> }
>
> }
>


----------------------------------------------------------------------------
----


> /*
>  * $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 apache@apache.org.
>  *
>  * 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;
> /*
>  * $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 apache@apache.org.
>  *
>  * 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/>.
>  *
>  */
> import junit.framework.TestCase;
>
> import org.apache.commons.collections.KeyValueRecord;
>
> /**
>  *
>  * @author Neil O'Toole
>  */
> public class TestKeyValueRecord extends TestCase
> {
> private final String key = "key";
> private final String value = "value";
> private final String previous = "previous";
>
> public TestKeyValueRecord(String testName)
> {
> super(testName);
>
> }
>
> public static void main(String[] args)
> {
> junit.textui.TestRunner.run(TestKeyValueRecord.class);
> }
>
> public void testKeyValueRecord()
> {
>
> // KVR with no previous value
> KeyValueRecord kvr = new KeyValueRecord(key, value);
>
> assertTrue(
> kvr.getKey() == key
> && kvr.getValue() == value
> && kvr.getPreviousValue() == null
> && kvr.hasPreviousValue() == false);
>
> assertTrue(kvr.equals(kvr));
> assertTrue(kvr.toString().equals("key=value"));
>
> // KVR with a previous value
> KeyValueRecord kvr2 = new KeyValueRecord(key, value, previous);
>
> assertTrue(
> kvr2.getKey() == key
> && kvr2.getValue() == value
> && kvr2.getPreviousValue() == previous
> && kvr2.hasPreviousValue() == true);
>
> assertTrue(kvr2.equals(kvr2));
> assertTrue(kvr2.toString().equals("key=value (previous)"));
>
> assertFalse(kvr.equals(kvr2));
> assertFalse(kvr.hashCode() == kvr2.hashCode());
>
> // test that a previous value of 'null' is treated differently to no
previous value
> KeyValueRecord kvr3 = new KeyValueRecord(key, value, null);
> assertTrue(kvr3.equals(kvr3));
> assertTrue(kvr3.toString().equals("key=value (null)"));
> assertFalse(kvr3.equals(kvr));
> assertFalse(kvr3.equals(kvr2));
>
> assertFalse(kvr3.hashCode() == kvr2.hashCode());
> assertFalse(kvr3.hashCode() == kvr.hashCode());
>
> // test the Map.Entry handling
> Map map = new HashMap();
> map.put(key, value);
>
> Map.Entry entry = (Map.Entry) map.entrySet().iterator().next();
>
> KeyValueRecord kvr4 = new KeyValueRecord(entry);
>
> assertTrue(
> kvr4.getKey() == key
> && kvr4.getValue() == value
> && kvr4.getPreviousValue() == null
> && kvr4.hasPreviousValue() == false);
>
> assertTrue(kvr4.equals(kvr4));
> assertTrue(kvr4.equals(kvr));
> assertTrue(kvr4.toString().equals("key=value"));
>
> assertFalse("Map.Entry and KeyValueRecord are never equal",
kvr4.equals(entry));
>
> Map.Entry entry2 = kvr4.asMapEntry();
>
> assertTrue(entry.equals(entry2));
> assertTrue(entry.hashCode() == entry2.hashCode());
>
> }
>
> }
>
>


----------------------------------------------------------------------------
----


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message