All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.spf4j.ds.CopyOnWriteMap Maven / Gradle / Ivy

Go to download

A continuously growing collection of utilities to measure performance, get better diagnostics, improve performance, or do things more reliably, faster that other open source libraries...

There is a newer version: 8.10.0
Show newest version
package org.spf4j.ds;


/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
import com.google.common.collect.Maps;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * A thread-safe version of {@link Map} in which all operations that change the Map are implemented by making a new copy
 * of the underlying Map.
 *
 * While the creation of a new Map can be expensive, this class is designed for cases in which the primary function is
 * to read data from the Map, not to modify the Map. Therefore the operations that do not cause a change to this class
 * happen quickly and concurrently.
 *
 * @author The Apache MINA Project ([email protected])
 * @version $Rev$, $Date$
 */
@SuppressFBWarnings(value = {"NOS_NON_OWNED_SYNCHRONIZATION"},
        justification = "Special case, not necessary on read path due to use of volatile")
public class CopyOnWriteMap implements Map, Cloneable {

  private volatile Map internalMap;

  /**
   * Creates a new instance of CopyOnWriteMap.
   *
   */
  public CopyOnWriteMap() {
    internalMap = new HashMap();
  }

  /**
   * Creates a new instance of CopyOnWriteMap with the specified initial size
   *
   * @param initialCapacity The initial size of the Map.
   */
  public CopyOnWriteMap(final int initialCapacity) {
    internalMap = new HashMap(initialCapacity);
  }

  /**
   * Creates a new instance of CopyOnWriteMap in which the initial data being held by this map is contained in the
   * supplied map.
   *
   * @param data A Map containing the initial contents to be placed into this class.
   */
  public CopyOnWriteMap(final Map data) {
    internalMap = new HashMap(data);
  }

  /**
   * @return a copy of this map, this is a fast operation.
   */
  public final CopyOnWriteMap copy() {
    return new CopyOnWriteMap<>(internalMap);
  }

  /**
   * Adds the provided key and value to this map.
   *
   * @see java.util.Map#put(java.lang.Object, java.lang.Object)
   */
  public V put(final K key, final V value) {
    synchronized (this) {
      Map newMap = Maps.newHashMapWithExpectedSize(internalMap.size() + 1);
      newMap.putAll(internalMap);
      V val = newMap.put(key, value);
      internalMap = newMap;
      return val;
    }
  }

  /**
   * Removed the value and key from this map based on the provided key.
   *
   * @see java.util.Map#remove(java.lang.Object)
   */
  public V remove(final Object key) {
    synchronized (this) {
      Map newMap = new HashMap(internalMap);
      V val = newMap.remove(key);
      internalMap = newMap;
      return val;
    }
  }

  /**
   * Inserts all the keys and values contained in the provided map to this map.
   *
   * @see java.util.Map#putAll(java.util.Map)
   */
  public void putAll(final Map newData) {
    synchronized (this) {
      Map newMap = Maps.newHashMapWithExpectedSize(internalMap.size() + newData.size());
      newMap.putAll(internalMap);
      newMap.putAll(newData);
      internalMap = newMap;
    }
  }

  /**
   * Removes all entries in this map.
   *
   * @see java.util.Map#clear()
   */
  public void clear() {
    synchronized (this) {
      internalMap = new HashMap(0);
    }
  }

  //
  //  Below are methods that do not modify
  //          the internal Maps
  /**
   * Returns the number of key/value pairs in this map.
   *
   * @see java.util.Map#size()
   */
  public int size() {
    return internalMap.size();
  }

  /**
   * Returns true if this map is empty, otherwise false.
   *
   * @see java.util.Map#isEmpty()
   */
  public boolean isEmpty() {
    return internalMap.isEmpty();
  }

  /**
   * Returns true if this map contains the provided key, otherwise this method return false.
   *
   * @see java.util.Map#containsKey(java.lang.Object)
   */
  public boolean containsKey(final Object key) {
    return internalMap.containsKey(key);
  }

  /**
   * Returns true if this map contains the provided value, otherwise this method returns false.
   *
   * @see java.util.Map#containsValue(java.lang.Object)
   */
  public boolean containsValue(final Object value) {
    return internalMap.containsValue(value);
  }

  /**
   * Returns the value associated with the provided key from this map.
   *
   * @see java.util.Map#get(java.lang.Object)
   */
  public V get(final Object key) {
    return internalMap.get(key);
  }

  /**
   * This method will return a read-only {@link Set}.
   */
  public Set keySet() {
    return internalMap.keySet();
  }

  /**
   * This method will return a read-only {@link Collection}.
   */
  public Collection values() {
    return internalMap.values();
  }

  /**
   * This method will return a read-only {@link Set}.
   */
  public Set> entrySet() {
    return internalMap.entrySet();
  }

  /**
   * @return a clone of this map. equivalent to copy()
   */
  @Override
  public CopyOnWriteMap clone() {
    try {
      return (CopyOnWriteMap) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new InternalError(e);
    }
  }

  /**
   * @return string representation of this map the includes the contents.
   */
  @Override
  public String toString() {
    return "CopyOnWriteMap{internalMap=" + internalMap + '}';
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy