View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.util;
    21
    22  import java.util.Collection;
    23  import java.util.HashMap;
    24  import java.util.Map;
    25  import java.util.Set;
    26
    27  /**
    28   * A thread-safe version of {@link Map} in which all operations that change the
    29   * Map are implemented by making a new copy of the underlying Map.
    30   *
    31   * While the creation of a new Map can be expensive, this class is designed for
    32   * cases in which the primary function is to read data from the Map, not to
    33   * modify the Map.  Therefore the operations that do not cause a change to this
    34   * class happen quickly and concurrently.
    35   *
    36   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    37   */
    38  public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
    39      private volatile Map<K, V> internalMap;
    40
    41      /**
    42       * Creates a new instance of CopyOnWriteMap.
    43       *
    44       */
    45      public CopyOnWriteMap() {
    46          internalMap = new HashMap<K, V>();
    47      }
    48
    49      /**
    50       * Creates a new instance of CopyOnWriteMap with the specified initial size
    51       *
    52       * @param initialCapacity
    53       *  The initial size of the Map.
    54       */
    55      public CopyOnWriteMap(int initialCapacity) {
    56          internalMap = new HashMap<K, V>(initialCapacity);
    57      }
    58
    59      /**
    60       * Creates a new instance of CopyOnWriteMap in which the
    61       * initial data being held by this map is contained in
    62       * the supplied map.
    63       *
    64       * @param data
    65       *  A Map containing the initial contents to be placed into
    66       *  this class.
    67       */
    68      public CopyOnWriteMap(Map<K, V> data) {
    69          internalMap = new HashMap<K, V>(data);
    70      }
    71
    72      /**
    73       * Adds the provided key and value to this map.
    74       *
    75       * @see java.util.Map#put(java.lang.Object, java.lang.Object)
    76       */
    77      public V put(K key, V value) {
    78          synchronized (this) {
    79              Map<K, V> newMap = new HashMap<K, V>(internalMap);
    80              V val = newMap.put(key, value);
    81              internalMap = newMap;
    82              return val;
    83          }
    84      }
    85
    86      /**
    87       * Removed the value and key from this map based on the
    88       * provided key.
    89       *
    90       * @see java.util.Map#remove(java.lang.Object)
    91       */
    92      public V remove(Object key) {
    93          synchronized (this) {
    94              Map<K, V> newMap = new HashMap<K, V>(internalMap);
    95              V val = newMap.remove(key);
    96              internalMap = newMap;
    97              return val;
    98          }
    99      }
    100
    101     /**
    102      * Inserts all the keys and values contained in the
    103      * provided map to this map.
    104      *
    105      * @see java.util.Map#putAll(java.util.Map)
    106      */
    107     public void putAll(Map<? extends K, ? extends V> newData) {
    108         synchronized (this) {
    109             Map<K, V> newMap = new HashMap<K, V>(internalMap);
    110             newMap.putAll(newData);
    111             internalMap = newMap;
    112         }
    113     }
    114
    115     /**
    116      * Removes all entries in this map.
    117      *
    118      * @see java.util.Map#clear()
    119      */
    120     public void clear() {
    121         synchronized (this) {
    122             internalMap = new HashMap<K, V>();
    123         }
    124     }
    125
    126     // ==============================================
    127     // ==== Below are methods that do not modify ====
    128     // ====         the internal Maps            ====
    129     // ==============================================
    130     /**
    131      * Returns the number of key/value pairs in this map.
    132      *
    133      * @see java.util.Map#size()
    134      */
    135     public int size() {
    136         return internalMap.size();
    137     }
    138
    139     /**
    140      * Returns true if this map is empty, otherwise false.
    141      *
    142      * @see java.util.Map#isEmpty()
    143      */
    144     public boolean isEmpty() {
    145         return internalMap.isEmpty();
    146     }
    147
    148     /**
    149      * Returns true if this map contains the provided key, otherwise
    150      * this method return false.
    151      *
    152      * @see java.util.Map#containsKey(java.lang.Object)
    153      */
    154     public boolean containsKey(Object key) {
    155         return internalMap.containsKey(key);
    156     }
    157
    158     /**
    159      * Returns true if this map contains the provided value, otherwise
    160      * this method returns false.
    161      *
    162      * @see java.util.Map#containsValue(java.lang.Object)
    163      */
    164     public boolean containsValue(Object value) {
    165         return internalMap.containsValue(value);
    166     }
    167
    168     /**
    169      * Returns the value associated with the provided key from this
    170      * map.
    171      *
    172      * @see java.util.Map#get(java.lang.Object)
    173      */
    174     public V get(Object key) {
    175         return internalMap.get(key);
    176     }
    177
    178     /**
    179      * This method will return a read-only {@link Set}.
    180      */
    181     public Set<K> keySet() {
    182         return internalMap.keySet();
    183     }
    184
    185     /**
    186      * This method will return a read-only {@link Collection}.
    187      */
    188     public Collection<V> values() {
    189         return internalMap.values();
    190     }
    191
    192     /**
    193      * This method will return a read-only {@link Set}.
    194      */
    195     public Set<Entry<K, V>> entrySet() {
    196         return internalMap.entrySet();
    197     }
    198
    199     @Override
    200     public Object clone() {
    201         try {
    202             return super.clone();
    203         } catch (CloneNotSupportedException e) {
    204             throw new InternalError();
    205         }
    206     }
    207 }