You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ma...@tumbleweed.com on 2001/11/01 03:01:06 UTC

Re: Fast Collection Classes

The collections classes have been moved to Jakarta Commons, so you might 
want to suggest your changes there (commons-dev@jakarta.apache.org).

Also, as James mentioned, attaching the changes in the form of a diff ('cvs 
diff -u' is the preferred form) will help people understand what you are 
proposing.

--
Martin Cooper


At 11:15 AM 10/31/01, Elie Levy wrote:
>I have done some changes to the FastHashMap class implementation.
>
>
>The modification that I have done only makes it easier to understand and to
>mantain the code for me. The same change can be applied to all the Fast
>Collection Classes, please tell me if you want me to do that.
>
>I would like to know what do you think about it.
>
>
>
>This is the first time that I send something to this list. I don't know if
>this is the way of doing it. Please let me know if this way is fine.
>
>Regards,
>
>
>
>
>
>eL.
>
>
>/*
>  * $Header:
>/home/cvs/jakarta-struts/src/share/org/apache/struts/util/FastHashMap.java,v
>1.4.2.1 2001/05/20 21:06:43 craigmcc Exp $
>  * $Revision: 1.4.2.1 $
>  * $Date: 2001/05/20 21:06:43 $
>  *
>  * ====================================================================
>  *
>  * The Apache Software License, Version 1.1
>  *
>  * Copyright (c) 1999-2001 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 acknowlegement:
>  *       "This product includes software developed by the
>  *        Apache Software Foundation (http://www.apache.org/)."
>  *    Alternately, this acknowlegement may appear in the software itself,
>  *    if and wherever such third-party acknowlegements normally appear.
>  *
>  * 4. The names "The Jakarta Project", "Struts", 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 Group.
>  *
>  * 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.struts.util;
>
>
>import java.io.Serializable;
>import java.util.Collection;
>import java.util.HashMap;
>import java.util.Iterator;
>import java.util.Map;
>import java.util.Map.Entry;
>import java.util.Set;
>
>
>/**
>  * <p>A customized implementation of <code>java.util.HashMap</code> designed
>  * to operate in a multithreaded environment where the large majority of
>  * method calls are read-only, instead of structural changes.  When operating
>  * in "fast" mode, read calls are non-synchronized and write calls perform
>the
>  * following steps:</p>
>  * <ul>
>  * <li>Clone the existing collection
>  * <li>Perform the modification on the clone
>  * <li>Replace the existing collection with the (modified) clone
>  * </ul>
>  * <p>When first created, objects of this class default to "slow" mode, where
>  * all accesses of any type are synchronized but no cloning takes place.
>This
>  * is appropriate for initially populating the collection, followed by a
>switch
>  * to "fast" mode (by calling <code>setFast(true)</code>) after
>initialization
>  * is complete.</p>
>  *
>  * <p><strong>NOTE</strong>: If you are creating and accessing a
>  * <code>HashMap</code> only within a single thread, you should use
>  * <code>java.util.HashMap</code> directly (with no synchronization), for
>  * maximum performance.</p>
>  *
>  * @deprecated At some point after Struts 1.0 final, will be replaced by
>  *  an equivalent class in the Jakarta Commons Collections package.
>  *
>  * @author Craig R. McClanahan
>  * @version $Revision: 1.4.2.1 $ $Date: 2001/05/20 21:06:43 $
>  */
>
>public class FastHashMap extends HashMap {
>
>
>     // -----------------------------------------------------------
>Constructors
>
>
>     /**
>      * Construct a an empty map.
>      */
>     public FastHashMap() {
>
>         super();
>         this.map = new HashMap();
>
>     }
>
>
>     /**
>      * Construct an empty map with the specified capacity.
>      *
>      * @param capacity The initial capacity of the empty map
>      */
>     public FastHashMap(int capacity) {
>
>         super();
>         this.map = new HashMap(capacity);
>
>     }
>
>
>     /**
>      * Construct an empty map with the specified capacity and load factor.
>      *
>      * @param capacity The initial capacity of the empty map
>      * @param factor The load factor of the new map
>      */
>     public FastHashMap(int capacity, float factor) {
>
>         super();
>         this.map = new HashMap(capacity, factor);
>
>     }
>
>
>     /**
>      * Construct a new map with the same mappings as the specified map.
>      *
>      * @param map The map whose mappings are to be copied
>      */
>     public FastHashMap(Map map) {
>
>         super();
>         this.map = new HashMap(map);
>
>     }
>
>
>     // ----------------------------------------------------- Instance
>Variables
>
>
>     /**
>      * The underlying map we are managing.
>      */
>     protected HashMap map = null;
>
>
>     // -------------------------------------------------------------
>Properties
>
>
>     /**
>      * Are we operating in "fast" mode?
>      */
>     protected boolean fast = false;
>
>     public boolean getFast() {
>         return (this.fast);
>     }
>
>     public void setFast(boolean fast) {
>         this.fast = fast;
>     }
>
>
>     // --------------------------------------------------------- Public
>Methods
>
>
>     /**
>      * Remove all mappings from this map.
>      */
>     public void clear() {
>
>         if (fast) {
>             synchronized (this) {
>                 HashMap temp = (HashMap) map.clone();
>                 temp.clear();
>                 map = temp;
>             }
>         } else {
>             synchronized (map) {
>                 map.clear();
>             }
>         }
>
>     }
>
>
>     /**
>      * Return a shallow copy of this <code>FastHashMap</code> instance.
>      * The keys and values themselves are not copied.
>      */
>     public Object clone() {
>
>         FastHashMap results = null;
>         if (fast) {
>             results = new FastHashMap(map);
>         } else {
>             synchronized (map) {
>                 results = new FastHashMap(map);
>             }
>         }
>         results.setFast(getFast());
>         return (results);
>
>     }
>
>
>     /**
>      * Return <code>true</code> if this map contains a mapping for the
>      * specified key.
>      *
>      * @param key Key to be searched for
>      */
>     public boolean containsKey(Object key) {
>
>         if (fast) {
>             return (map.containsKey(key));
>         } else {
>             synchronized (map) {
>                 return (map.containsKey(key));
>             }
>         }
>
>     }
>
>
>     /**
>      * Return <code>true</code> if this map contains one or more keys mapping
>      * to the specified value.
>      *
>      * @param value Value to be searched for
>      */
>     public boolean containsValue(Object value) {
>
>         if (fast) {
>             return (map.containsValue(value));
>         } else {
>             synchronized (map) {
>                 return (map.containsValue(value));
>             }
>         }
>
>     }
>
>
>     /**
>      * Return a collection view of the mappings contained in this map.  Each
>      * element in the returned collection is a <code>Map.Entry</code>.
>      */
>     public Set entrySet() {
>
>         if (fast) {
>             return (map.entrySet());
>         } else {
>             synchronized (map) {
>                 return (map.entrySet());
>             }
>         }
>
>     }
>
>
>     /**
>      * Compare the specified object with this list for equality.  This
>      * implementation uses exactly the code that is used to define the
>      * list equals function in the documentation for the
>      * <code>Map.equals</code> method.
>      *
>      * @param o Object to be compared to this list
>      */
>     public boolean equals(Object o) {
>
>         // Simple tests that require no synchronization
>         if (o == this)
>             return (true);
>         else if (!(o instanceof Map))
>             return (false);
>         Map mo = (Map) o;
>
>         // Compare the two maps for equality
>         return (fast)?stdEquals(o):synchEquals(o);
>     }
>
>     /**
>      * Compare the specified object with this list for equality. This
>      * is a helper method for the public implementation. It is used when not
>in
>      * fast mode.
>      *
>      * @param o Object to be compared to this list
>      */
>     private boolean synchEquals(Object o) {
>         synchronized (map) {
>             return stdEquals(o);
>         }
>     }
>
>     /**
>      * Compare the specified object with this list for equality. This
>      * is a helper method for the public implementation.
>      *
>      * @param o Object to be compared to this list
>      */
>     private boolean stdEquals(Object object) {
>
>         if (mo.size() != map.size())
>                 return (false);
>             java.util.Iterator i = map.entrySet().iterator();
>             while (i.hasNext()) {
>                 Map.Entry e = (Map.Entry) i.next();
>                 Object key = e.getKey();
>                 Object value = e.getValue();
>                 if (value == null) {
>                     if (!(mo.get(key) == null && mo.containsKey(key)))
>                         return (false);
>                 } else {
>                     if (!value.equals(mo.get(key)))
>                         return (false);
>                 }
>             }
>             return (true);
>
>     }
>
>     /**
>      * Return the value to which this map maps the specified key.  Returns
>      * <code>null</code> if the map contains no mapping for this key, or if
>      * there is a mapping with a value of <code>null</code>.  Use the
>      * <code>containsKey()</code> method to disambiguate these cases.
>      *
>      * @param key Key whose value is to be returned
>      */
>     public Object get(Object key) {
>
>         if (fast) {
>             return (map.get(key));
>         } else {
>             synchronized (map) {
>                 return (map.get(key));
>             }
>         }
>
>     }
>
>
>     /**
>      * Return the hash code value for this map.  This implementation uses
>      * exactly the code that is used to define the list hash function in the
>      * documentation for the <code>Map.hashCode</code> method.
>      */
>     public int hashCode() {
>         return (fast)?stdHashCode():synchHashCode();
>     }
>
>     /**
>      * Returns the hash code value for htis map. This implementation is
>      * a helper method for the public interface
>      */
>     private int synchHashCode() {
>
>         synchronized (map) {
>                 return stdHashCode();
>             }
>
>     }
>
>     /**
>      * Return the hash code value for this map. This implementation
>      * is a helper method for the public interface
>      */
>     private int stdHashCode() {
>
>         int h = 0;
>         java.util.Iterator i = map.entrySet().iterator();
>         while (i.hasNext())
>             h += i.next().hashCode();
>         return (h);
>
>     }
>
>     /**
>      * Return <code>true</code> if this map contains no mappings.
>      */
>     public boolean isEmpty() {
>
>         if (fast) {
>             return (map.isEmpty());
>         } else {
>             synchronized (map) {
>                 return (map.isEmpty());
>             }
>         }
>
>     }
>
>
>     /**
>      * Return a set view of the keys contained in this map.
>      */
>     public Set keySet() {
>
>         if (fast) {
>             return (map.keySet());
>         } else {
>             synchronized (map) {
>                 return (map.keySet());
>             }
>         }
>
>     }
>
>
>     /**
>      * Associate the specified value with the specified key in this map.
>      * If the map previously contained a mapping for this key, the old
>      * value is replaced and returned.
>      *
>      * @param key The key with which the value is to be associated
>      * @param value The value to be associated with this key
>      */
>     public Object put(Object key, Object value) {
>
>         if (fast) {
>             synchronized (this) {
>                 HashMap temp = (HashMap) map.clone();
>                 Object result = temp.put(key, value);
>                 map = temp;
>                 return (result);
>             }
>         } else {
>             synchronized (map) {
>                 return (map.put(key, value));
>             }
>         }
>
>     }
>
>
>     /**
>      * Copy all of the mappings from the specified map to this one, replacing
>      * any mappings with the same keys.
>      *
>      * @param in Map whose mappings are to be copied
>      */
>     public void putAll(Map in) {
>
>         if (fast) {
>             synchronized (this) {
>                 HashMap temp = (HashMap) map.clone();
>                 temp.putAll(in);
>                 map = temp;
>             }
>         } else {
>             synchronized (map) {
>                 map.putAll(in);
>             }
>         }
>
>     }
>
>
>     /**
>      * Remove any mapping for this key, and return any previously
>      * mapped value.
>      *
>      * @param key Key whose mapping is to be removed
>      */
>     public Object remove(Object key) {
>
>         if (fast) {
>             synchronized (this) {
>                 HashMap temp = (HashMap) map.clone();
>                 Object result = temp.remove(key);
>                 map = temp;
>                 return (result);
>             }
>         } else {
>             synchronized (map) {
>                 return (map.remove(key));
>             }
>         }
>     }
>
>
>     /**
>      * Return the number of key-value mappings in this map.
>      */
>     public int size() {
>
>         if (fast) {
>             return (map.size());
>         } else {
>             synchronized (map) {
>                 return (map.size());
>             }
>         }
>     }
>
>
>     /**
>      * Return a collection view of the values contained in this map.
>      */
>     public Collection values() {
>
>         if (fast) {
>             return (map.values());
>         } else {
>             synchronized (map) {
>                 return (map.values());
>             }
>         }
>     }
>}
>
>
>--
>To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
>For additional commands, e-mail: <ma...@jakarta.apache.org>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>