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

com.tangosol.util.CopyOnWriteMap Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
package com.tangosol.util;


import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


/**
 * A thread-safe variant of {@link Map} in which all mutating operations
 * (e.g. {@code put}, {@code putAll}) are implemented by making a fresh copy of
 * the underlying map.
 * 

* Iterators over this map are guaranteed to produce a safe-iteration and * not to throw {@code ConcurrentModificationException}. The iterator will not * reflect concurrent additions, removals, or changes to this map. *

* Note: mutations on this map are costly, but may be more * efficient than alternatives when "get" operations vastly outnumber * mutations. All mutating operations are synchronized, so concurrent mutation * can be prevented by holding synchronization on this object. * * @since Coherence 3.7.2 * * @author pp 2011.09.17, rhl 2010.09.09 (from CopyOnWriteLongArray) */ public class CopyOnWriteMap implements Map { // ----- constructors ------------------------------------------------- public CopyOnWriteMap(Class clazz) { setInternalMap(instantiateMap(clazz)); } /** * Construct a CopyOnWriteMap, initialized with the contents of the * specified map. * * @param map the initial map */ public CopyOnWriteMap(Map map) { setInternalMap(copyMap(map)); } // ----- accessors ---------------------------------------------------- /** * Return the internal map. * * @return the internal map */ protected Map getInternalMap() { return m_mapInternal; } /** * Set the internal map. * * @param map the new internal map */ protected void setInternalMap(Map map) { m_mapInternal = map; } // ----- helpers ------------------------------------------------------ /** * Create a new instance of {@link Map} based on the provided {@link Class}. * * @param clazz the type of {@link Map} to instantiate * * @return a new empty instance of {@link Map} * * @throws IllegalArgumentException if the provided {@link Class} does not implement {@link Map}. */ protected Map instantiateMap(Class clazz) { if (!Map.class.isAssignableFrom(clazz)) { throw new IllegalArgumentException("Expected a class assignable from java.util.Map instead of " + clazz.getName()); } try { return (Map) clazz.newInstance(); } catch (Exception e) { throw Base.ensureRuntimeException(e, "Could not create new instance of " + clazz.getName()); } } /** * Create an instance of {@link Map} based on the contents of the provided map. * * @param map the map to copy * * @return an instance of {@link Map} populated with the contents of the provided map */ protected Map copyMap(Map map) { Map mapNew = instantiateMap(map.getClass()); mapNew.putAll(map); return mapNew; } // ----- Map methods -------------------------------------------------- /** * {@inheritDoc} */ public int size() { return getInternalMap().size(); } /** * {@inheritDoc} */ public boolean isEmpty() { return getInternalMap().isEmpty(); } /** * {@inheritDoc} */ public boolean containsKey(Object oKey) { return getInternalMap().containsKey(oKey); } /** * {@inheritDoc} */ public boolean containsValue(Object oValue) { return getInternalMap().containsValue(oValue); } /** * {@inheritDoc} */ public V get(Object oKey) { return getInternalMap().get(oKey); } /** * {@inheritDoc} */ public synchronized V put(K oKey, V oValue) { Map mapNew = copyMap(getInternalMap()); V oValueOld = mapNew.put(oKey, oValue); setInternalMap(mapNew); return oValueOld; } /** * {@inheritDoc} */ public synchronized V remove(Object oKey) { Map mapNew = copyMap(getInternalMap()); V oValueOld = mapNew.remove(oKey); setInternalMap(mapNew); return oValueOld; } /** * {@inheritDoc} */ public synchronized void putAll(Map map) { Map mapNew = copyMap(getInternalMap()); mapNew.putAll(map); setInternalMap(mapNew); } /** * {@inheritDoc} */ public synchronized void clear() { setInternalMap(instantiateMap(m_mapInternal.getClass())); } /** * Returns a Set view of the keys contained in the underlying map. * * @return a Set view of the keys contained in the underlying map */ public Set keySet() { KeySet set = m_setKeys; if (set == null) { m_setKeys = set = new KeySet(); } return set; } /** * Return a set view of the underlying map. * * @return a set view of the underlying map */ public Set> entrySet() { EntrySet set = m_setEntries; if (set == null) { m_setEntries = set = new EntrySet(); } return set; } /** * {@inheritDoc} */ public Collection values() { return Collections.unmodifiableCollection(getInternalMap().values()); } // ----- inner class: KeySet -------------------------------------------- /** * A set of keys backed by this map. */ protected class KeySet extends AbstractSet { // ----- Set interface ------------------------------------------ /** * {@inheritDoc} */ @Override public Iterator iterator() { return new Iterator() { public boolean hasNext() { return m_iter.hasNext(); } public K next() { return m_keyNext = m_iter.next(); } public void remove() { CopyOnWriteMap.this.remove(m_keyNext); m_keyNext = null; } private Iterator m_iter = CopyOnWriteMap.this.getInternalMap().keySet().iterator(); private K m_keyNext; }; } /** * {@inheritDoc} */ @Override public int size() { return CopyOnWriteMap.this.size(); } /** * {@inheritDoc} */ @Override public boolean contains(Object oKey) { return CopyOnWriteMap.this.containsKey(oKey); } /** * {@inheritDoc} */ @Override public boolean remove(Object o) { CopyOnWriteMap map = CopyOnWriteMap.this; if (map.containsKey(o)) { map.remove(o); return true; } else { return false; } } /** * {@inheritDoc} */ @Override public boolean removeAll(Collection coll) { assert coll != null; boolean fRemoved; synchronized (CopyOnWriteMap.this) { Map mapNew = copyMap(getInternalMap()); fRemoved = mapNew.keySet().removeAll(coll); setInternalMap(mapNew); } return fRemoved; } /** * {@inheritDoc} */ public void clear() { CopyOnWriteMap.this.clear(); } } // ----- inner class: EntrySet ------------------------------------------ /** * A set of entries backed by this map. */ protected class EntrySet extends AbstractSet> { // ----- Set interface ------------------------------------------ /** * {@inheritDoc} */ @Override public Iterator> iterator() { return new Iterator() { public boolean hasNext() { return m_iter.hasNext(); } public Entry next() { return m_entryNext = m_iter.next(); } public void remove() { CopyOnWriteMap.this.remove(m_entryNext.getKey()); m_entryNext = null; } private Iterator> m_iter = CopyOnWriteMap.this.getInternalMap().entrySet().iterator(); private Entry m_entryNext; }; } /** * {@inheritDoc} */ @Override public int size() { return CopyOnWriteMap.this.size(); } /** * {@inheritDoc} */ @Override public boolean contains(Object o) { if (o instanceof Entry) { Entry entryThat = (Entry) o; Entry entryThis = (Entry) CopyOnWriteMap.this.get(entryThat.getKey()); return entryThis != null && entryThis.equals(entryThat); } return false; } /** * {@inheritDoc} */ @Override public boolean remove(Object o) { CopyOnWriteMap map = CopyOnWriteMap.this; if (contains(o)) { map.remove(((Map.Entry) o).getKey()); return true; } else { return false; } } /** * {@inheritDoc} */ @Override public void clear() { CopyOnWriteMap.this.clear(); } } // ----- Object methods ----------------------------------------------- /** * {@inheritDoc} */ public boolean equals(Object o) { if (this == o) { return true; } CopyOnWriteMap that = (CopyOnWriteMap) o; return Base.equals(this.m_mapInternal, that.m_mapInternal); } /** * {@inheritDoc} */ public int hashCode() { return m_mapInternal == null ? 0 : m_mapInternal.hashCode(); } /** * {@inheritDoc} */ public String toString() { return "CopyOnWriteMap{" + m_mapInternal + "}"; } // ----- constants and data members ----------------------------------- /** * The internal map. */ private volatile Map m_mapInternal; /** * The set of keys backed by this map. */ private KeySet m_setKeys; /** * The set of entries backed by this map. */ private EntrySet m_setEntries; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy