Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * JBoss, Home of Professional Open Source.
    * Copyright 2010, Red Hat, Inc., and individual contributors
    * as indicated by the @author tags. See the copyright.txt file in the
    * distribution for a full listing of individual contributors.
    *
    * This is free software; you can redistribute it and/or modify it
    * under the terms of the GNU Lesser General Public License as
    * published by the Free Software Foundation; either version 2.1 of
   * the License, or (at your option) any later version.
   *
   * This software is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this software; if not, write to the Free
   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   */
  
  /*
   * Written by Doug Lea with assistance from members of JCP JSR-166
   * Expert Group and released to the public domain, as explained at
   * http://creativecommons.org/licenses/publicdomain
   */
  
  package org.hibernate.validator.internal.util;
  import java.util.EnumSet;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
An advanced hash table supporting configurable garbage collection semantics of keys and values, optional referential-equality, full concurrency of retrievals, and adjustable expected concurrency for updates. This table is designed around specific advanced use-cases. If there is any doubt whether this table is for you, you most likely should be using java.util.concurrent.ConcurrentHashMap instead. This table supports strong, weak, and soft keys and values. By default keys are weak, and values are strong. Such a configuration offers similar behavior to java.util.WeakHashMap, entries of this table are periodically removed once their corresponding keys are no longer referenced outside of this table. In other words, this table will not prevent a key from being discarded by the garbage collector. Once a key has been discarded by the collector, the corresponding entry is no longer visible to this table; however, the entry may occupy space until a future table operation decides to reclaim it. For this reason, summary functions such as size and isEmpty might return a value greater than the observed number of entries. In order to support a high level of concurrency, stale entries are only reclaimed during blocking (usually mutating) operations. Enabling soft keys allows entries in this table to remain until their space is absolutely needed by the garbage collector. This is unlike weak keys which can be reclaimed as soon as they are no longer referenced by a normal strong reference. The primary use case for soft keys is a cache, which ideally occupies memory that is not in use for as long as possible. By default, values are held using a normal strong reference. This provides the commonly desired guarantee that a value will always have at least the same life-span as it's key. For this reason, care should be taken to ensure that a value never refers, either directly or indirectly, to its key, thereby preventing reclamation. If this is unavoidable, then it is recommended to use the same reference type in use for the key. However, it should be noted that non-strong values may disappear before their corresponding key. While this table does allow the use of both strong keys and values, it is recommended to use java.util.concurrent.ConcurrentHashMap for such a configuration, since it is optimized for that case. Just like java.util.concurrent.ConcurrentHashMap, this class obeys the same functional specification as java.util.Hashtable, and includes versions of methods corresponding to each method of Hashtable. However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset. For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw java.util.ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.

The allowed concurrency among update operations is guided by the optional concurrencyLevel constructor argument (default 16), which is used as a hint for internal sizing. The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. Because placement in hash tables is essentially random, the actual concurrency will vary. Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table. Using a significantly higher value than you need can waste space and time, and a significantly lower value can lead to thread contention. But overestimates and underestimates within an order of magnitude do not usually have much noticeable impact. A value of one is appropriate when it is known that only one thread will modify and all others will only read. Also, resizing this or any other kind of hash table is a relatively slow operation, so, when possible, it is a good idea to provide estimates of expected table sizes in constructors.

This class and its views and iterators implement all of the optional methods of the java.util.Map and java.util.Iterator interfaces.

Like java.util.Hashtable but unlike java.util.HashMap, this class does not allow null to be used as a key or value.

This class is a member of the Java Collections Framework.

Parameters:
<K> the type of keys maintained by this map
<V> the type of mapped values
Author(s):
Doug Lea
Jason T. Greene
 
 final public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V>
 		implements java.util.concurrent.ConcurrentMap<K, V>, Serializable {
 	private static final long serialVersionUID = 7249069246763182397L;
 
 	/*
 		 * The basic strategy is to subdivide the table among Segments,
 		 * each of which itself is a concurrently readable hash table.
 		 */

An option specifying which Java reference type should be used to refer to a key and/or value.
 
 	public static enum ReferenceType {
Indicates a normal Java strong reference should be used
 
 		STRONG,
Indicates a java.lang.ref.WeakReference should be used
 
 		WEAK,
Indicates a java.lang.ref.SoftReference should be used
 
 		SOFT
 	};
 
 
 	public static enum Option {
Indicates that referential-equality (== instead of .equals()) should be used when locating keys. This offers similar behavior to java.util.IdentityHashMap
 
 		IDENTITY_COMPARISONS
 	};
 
 	/* ---------------- Constants -------------- */
 
 
The default initial capacity for this table, used when not otherwise specified in a constructor.
 
 	static final int DEFAULT_INITIAL_CAPACITY = 16;

The default load factor for this table, used when not otherwise specified in a constructor.
 
 	static final float DEFAULT_LOAD_FACTOR = 0.75f;

The default concurrency level for this table, used when not otherwise specified in a constructor.
 
 	static final int DEFAULT_CONCURRENCY_LEVEL = 16;

The maximum capacity, used if a higher value is implicitly specified by either of the constructors with arguments. MUST be a power of two <= 1<<30 to ensure that entries are indexable using ints.
 
 	static final int MAXIMUM_CAPACITY = 1 << 30;

The maximum number of segments to allow; used to bound constructor arguments.
 
 	static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
 
Number of unsynchronized retries in size and containsValue methods before resorting to locking. This is used to avoid unbounded retries if tables undergo continuous modification which would make it impossible to obtain an accurate result.
 
 	static final int RETRIES_BEFORE_LOCK = 2;
 
 	/* ---------------- Fields -------------- */

Mask value for indexing into segments. The upper bits of a key's hash code are used to choose the segment.
 
 	final int segmentMask;

Shift value for indexing within segments.
 
 	final int segmentShift;

The segments, each of which is a specialized hash table
 
 	final Segment<K,V>[] segments;
 
 
 	transient Set<K> keySet;
 	transient Set<Map.Entry<K,V>> entrySet;
 	transient Collection<V> values;
 
 	/* ---------------- Small Utilities -------------- */

Applies a supplemental hash function to a given hashCode, which defends against poor quality hash functions. This is critical because ConcurrentReferenceHashMap uses power-of-two length hash tables, that otherwise encounter collisions for hashCodes that do not differ in lower or upper bits.
 
 	private static int hash(int h) {
 		// Spread bits to regularize both segment and index locations,
 		// using variant of single-word Wang/Jenkins hash.
 		h += (h <<  15) ^ 0xffffcd7d;
 		h ^= (h >>> 10);
 		h += (h <<   3);
 		h ^= (h >>>  6);
 		h += (h <<   2) + (h << 14);
 		return h ^ (h >>> 16);
 	}

Returns the segment that should be used for key with given hash

Parameters:
hash the hash code for the key
Returns:
the segment
 
 	final Segment<K,V> segmentFor(int hash) {
 		return [(hash >>> ) & ];
 	}
 
 	private int hashOf(Object key) {
 				System.identityHashCode(key) : key.hashCode());
 	}
 
 	/* ---------------- Inner Classes -------------- */
 
 	static interface KeyReference {
 		int keyHash();
 	}

A weak-key reference which stores the key hash needed for reclamation.
 
 	static final class WeakKeyReference<K> extends WeakReference<K>  implements KeyReference {
 		final int hash;
 		WeakKeyReference(K keyint hashReferenceQueue<ObjectrefQueue) {
 			super(keyrefQueue);
 			this. = hash;
 		}
 		public final int keyHash() {
 			return ;
 		}
 
 		public final Object keyRef() {
 			return this;
 		}
 	}

A soft-key reference which stores the key hash needed for reclamation.
 
 	static final class SoftKeyReference<K> extends SoftReference<K> implements KeyReference {
 		final int hash;
 		SoftKeyReference(K keyint hashReferenceQueue<ObjectrefQueue) {
 			super(keyrefQueue);
 			this. = hash;
 		}
 		public final int keyHash() {
 			return ;
 		}
 
 		public final Object keyRef() {
 			return this;
 		}
 	}
 
 	static final class WeakValueReference<V> extends WeakReference<V>  implements KeyReference {
 		final Object keyRef;
 		final int hash;
 		WeakValueReference(V valueObject keyRefint hashReferenceQueue<ObjectrefQueue) {
 			super(valuerefQueue);
 			this. = keyRef;
 			this. = hash;
 		}
 
 		public final int keyHash() {
 			return ;
 		}
 
 		public final Object keyRef() {
 			return ;
 		}
 	}
 
 	static final class SoftValueReference<V> extends SoftReference<V>  implements KeyReference {
 		final Object keyRef;
 		final int hash;
 		SoftValueReference(V valueObject keyRefint hashReferenceQueue<ObjectrefQueue) {
 			super(valuerefQueue);
 			this. = keyRef;
 			this. = hash;
 		}
 		public final int keyHash() {
 			return ;
 		}
 
 		public final Object keyRef() {
 			return ;
 		}
 	}

ConcurrentReferenceHashMap list entry. Note that this is never exported out as a user-visible Map.Entry. Because the value field is volatile, not final, it is legal wrt the Java Memory Model for an unsynchronized reader to see null instead of initial value when read via a data race. Although a reordering leading to this is not likely to ever actually occur, the Segment.readValueUnderLock method is used as a backup in case a null (pre-initialized) value is ever seen in an unsynchronized access method.
 
 	static final class HashEntry<K,V> {
 		final Object keyRef;
 		final int hash;
 		volatile Object valueRef;
 		final HashEntry<K,V> next;
 
 		HashEntry(K keyint hash,  HashEntry<K,V> next, V value,
 				  ReferenceType keyTypeReferenceType valueType,
 				  ReferenceQueue<ObjectrefQueue) {
 			this. = hash;
 			this. = next;
 			this. = newKeyReference(keykeyTyperefQueue);
 			this. = newValueReference(valuevalueTyperefQueue);
 		}
 
 		final Object newKeyReference(K keyReferenceType keyType,
 									 ReferenceQueue<ObjectrefQueue) {
 			if (keyType == .)
 				return new WeakKeyReference<K>(keyrefQueue);
 			if (keyType == .)
 				return new SoftKeyReference<K>(keyrefQueue);
 
 			return key;
 		}
 
 		final Object newValueReference(V valueReferenceType valueType,
 									   ReferenceQueue<ObjectrefQueue) {
 			if (valueType == .)
 				return new WeakValueReference<V>(valuerefQueue);
 			if (valueType == .)
 				return new SoftValueReference<V>(valuerefQueue);
 
 			return value;
 		}
 
 		@SuppressWarnings("unchecked")
 		final K key() {
 			if ( instanceof KeyReference)
 				return ((Reference<K>)).get();
 
 			return (K) ;
 		}
 
 		final V value() {
 		}
 
 		@SuppressWarnings("unchecked")
 		final V dereferenceValue(Object value) {
 			if (value instanceof KeyReference)
 				return ((Reference<V>)value).get();
 
 			return (V) value;
 		}
 
 		final void setValue(V valueReferenceType valueTypeReferenceQueue<ObjectrefQueue) {
 			this. = newValueReference(valuevalueTyperefQueue);
 		}
 
 		@SuppressWarnings("unchecked")
 		static final <K,V> HashEntry<K,V>[] newArray(int i) {
 			return new HashEntry[i];
 		}
 	}

Segments are specialized versions of hash tables. This subclasses from ReentrantLock opportunistically, just to simplify some locking and avoid separate construction.
 
 	static final class Segment<K,V> extends ReentrantLock implements Serializable {
 		/*
 				 * Segments maintain a table of entry lists that are ALWAYS
 				 * kept in a consistent state, so can be read without locking.
 				 * Next fields of nodes are immutable (final).  All list
 				 * additions are performed at the front of each bin. This
 				 * makes it easy to check changes, and also fast to traverse.
 				 * When nodes would otherwise be changed, new nodes are
 				 * created to replace them. This works well for hash tables
 				 * since the bin lists tend to be short. (The average length
 				 * is less than two for the default load factor threshold.)
 				 *
 				 * Read operations can thus proceed without locking, but rely
 				 * on selected uses of volatiles to ensure that completed
 				 * write operations performed by other threads are
 				 * noticed. For most purposes, the "count" field, tracking the
 				 * number of elements, serves as that volatile variable
 				 * ensuring visibility.  This is convenient because this field
 				 * needs to be read in many read operations anyway:
 				 *
 				 *   - All (unsynchronized) read operations must first read the
 				 *     "count" field, and should not look at table entries if
 				 *     it is 0.
 				 *
 				 *   - All (synchronized) write operations should write to
 				 *     the "count" field after structurally changing any bin.
 				 *     The operations must not take any action that could even
 				 *     momentarily cause a concurrent read operation to see
 				 *     inconsistent data. This is made easier by the nature of
 				 *     the read operations in Map. For example, no operation
 				 *     can reveal that the table has grown but the threshold
 				 *     has not yet been updated, so there are no atomicity
 				 *     requirements for this with respect to reads.
 				 *
 				 * As a guide, all critical volatile reads and writes to the
 				 * count field are marked in code comments.
 				 */
 
 		private static final long serialVersionUID = 2249069246763182397L;

The number of elements in this segment's region.
 
 		transient volatile int count;

Number of updates that alter the size of the table. This is used during bulk-read methods to make sure they see a consistent snapshot: If modCounts change during a traversal of segments computing size or checking containsValue, then we might have an inconsistent view of state so (usually) must retry.
 
 		transient int modCount;

The table is rehashed when its size exceeds this threshold. (The value of this field is always (int)(capacity * loadFactor).)
 
 		transient int threshold;

The per-segment table.
 
 		transient volatile HashEntry<K,V>[] table;

The load factor for the hash table. Even though this value is same for all segments, it is replicated to avoid needing links to outer object.

Serial:
 
 		final float loadFactor;

The collected weak-key reference queue for this segment. This should be (re)initialized whenever table is assigned,
 
 		transient volatile ReferenceQueue<ObjectrefQueue;
 
 
 
 		final boolean identityComparisons;
 
 		Segment(int initialCapacityfloat lfReferenceType keyType,
 				ReferenceType valueTypeboolean identityComparisons) {
 			 = lf;
 			this. = keyType;
 			this. = valueType;
 			this. = identityComparisons;
 			setTable(HashEntry.<K,V>newArray(initialCapacity));
 		}
 
 		@SuppressWarnings("unchecked")
 		static final <K,V> Segment<K,V>[] newArray(int i) {
 			return new Segment[i];
 		}
 
 		private boolean keyEq(Object srcObject dest) {
 			return  ? src == dest : src.equals(dest);
 		}

Sets table to new HashEntry array. Call only while holding lock or in constructor.
 
 		void setTable(HashEntry<K,V>[] newTable) {
 			 = (int)(newTable.length * );
 			 = newTable;
 		}

Returns properly casted first entry of bin for given hash.
 
 		HashEntry<K,V> getFirst(int hash) {
 			HashEntry<K,V>[] tab = ;
 			return tab[hash & (tab.length - 1)];
 		}
 
 		HashEntry<K,V> newHashEntry(K keyint hashHashEntry<K, V> next, V value) {
 			return new HashEntry<K,V>(keyhashnextvalue);
 		}

Reads value field of an entry under lock. Called if value field ever appears to be null. This is possible only if a compiler happens to reorder a HashEntry initialization with its table assignment, which is legal under memory model but is not known to ever occur.
 
 			lock();
 			try {
 				return e.value();
 			} finally {
 				unlock();
 			}
 		}
 
 		/* Specialized implementations of map methods */
 
 		V get(Object keyint hash) {
 			if ( != 0) { // read-volatile
 				HashEntry<K,V> e = getFirst(hash);
 				while (e != null) {
 					if (e.hash == hash && keyEq(keye.key())) {
 						Object opaque = e.valueRef;
 						if (opaque != null)
 							return e.dereferenceValue(opaque);
 
 						return readValueUnderLock(e);  // recheck
 					}
 					e = e.next;
 				}
 			}
 			return null;
 		}
 
 		boolean containsKey(Object keyint hash) {
 			if ( != 0) { // read-volatile
 				HashEntry<K,V> e = getFirst(hash);
 				while (e != null) {
 					if (e.hash == hash && keyEq(keye.key()))
 						return true;
 					e = e.next;
 				}
 			}
 			return false;
 		}
 
 		boolean containsValue(Object value) {
 			if ( != 0) { // read-volatile
 				HashEntry<K,V>[] tab = ;
 				int len = tab.length;
 				for (int i = 0 ; i < leni++) {
 					for (HashEntry<K,V> e = tab[i]; e != nulle = e.next) {
 						Object opaque = e.valueRef;
 						V v;
 
 						if (opaque == null)
 							v = readValueUnderLock(e); // recheck
 						else
 							v = e.dereferenceValue(opaque);
 
 						if (value.equals(v))
 							return true;
 					}
 				}
 			}
 			return false;
 		}
 
 		boolean replace(K keyint hash, V oldValue, V newValue) {
 			lock();
 			try {
 				HashEntry<K,V> e = getFirst(hash);
 				while (e != null && (e.hash != hash || !keyEq(keye.key())))
 					e = e.next;
 
 				boolean replaced = false;
 				if (e != null && oldValue.equals(e.value())) {
 					replaced = true;
 					e.setValue(newValue);
 				}
 				return replaced;
 			} finally {
 				unlock();
 			}
 		}
 
 		V replace(K keyint hash, V newValue) {
 			lock();
 			try {
 				HashEntry<K,V> e = getFirst(hash);
 				while (e != null && (e.hash != hash || !keyEq(keye.key())))
 					e = e.next;
 
 				V oldValue = null;
 				if (e != null) {
 					oldValue = e.value();
 					e.setValue(newValue);
 				}
 				return oldValue;
 			} finally {
 				unlock();
 			}
 		}
 
 
 		V put(K keyint hash, V valueboolean onlyIfAbsent) {
 			lock();
 			try {
 				int c = ;
 				if (c++ > ) {// ensure capacity
 					int reduced = rehash();
 					if (reduced > 0)  // adjust from possible weak cleanups
 						 = (c -= reduced) - 1; // write-volatile
 				}
 
 				HashEntry<K,V>[] tab = ;
 				int index = hash & (tab.length - 1);
 				HashEntry<K,V> first = tab[index];
 				HashEntry<K,V> e = first;
 				while (e != null && (e.hash != hash || !keyEq(keye.key())))
 					e = e.next;
 
 				V oldValue;
 				if (e != null) {
 					oldValue = e.value();
 					if (!onlyIfAbsent || oldValue == null// null = gc AFTER stale removal
 						e.setValue(value);
 				}
 				else {
 					oldValue = null;
 					tab[index] = newHashEntry(keyhashfirstvalue);
 					 = c// write-volatile
 				}
 				return oldValue;
 			} finally {
 				unlock();
 			}
 		}
 
 		int rehash() {
 			HashEntry<K,V>[] oldTable = ;
 			int oldCapacity = oldTable.length;
 			if (oldCapacity >= )
 				return 0;
 
 			/*
 						 * Reclassify nodes in each list to new Map.  Because we are
 						 * using power-of-two expansion, the elements from each bin
 						 * must either stay at same index, or move with a power of two
 						 * offset. We eliminate unnecessary node creation by catching
 						 * cases where old nodes can be reused because their next
 						 * fields won't change. Statistically, at the default
 						 * threshold, only about one-sixth of them need cloning when
 						 * a table doubles. The nodes they replace will be garbage
 						 * collectable as soon as they are no longer referenced by any
 						 * reader thread that may be in the midst of traversing table
 						 * right now.
 						 */
 
 			HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
 			 = (int)(newTable.length * );
 			int sizeMask = newTable.length - 1;
 			int reduce = 0;
 			for (int i = 0; i < oldCapacity ; i++) {
 				// We need to guarantee that any existing reads of old Map can
 				//  proceed. So we cannot yet null out each bin.
 				HashEntry<K,V> e = oldTable[i];
 
 				if (e != null) {
 					HashEntry<K,V> next = e.next;
 					int idx = e.hash & sizeMask;
 
 					//  Single node on list
 					if (next == null)
 						newTable[idx] = e;
 
 					else {
 						// Reuse trailing consecutive sequence at same slot
 						HashEntry<K,V> lastRun = e;
 						int lastIdx = idx;
 						for (HashEntry<K,V> last = next;
 							 last != null;
 							 last = last.next) {
 							int k = last.hash & sizeMask;
 							if (k != lastIdx) {
 								lastIdx = k;
 								lastRun = last;
 							}
 						}
 						newTable[lastIdx] = lastRun;
 						// Clone all remaining nodes
 						for (HashEntry<K,V> p = ep != lastRunp = p.next) {
 							// Skip GC'd weak refs
 							K key = p.key();
 							if (key == null) {
 								reduce++;
 								continue;
 							}
 							int k = p.hash & sizeMask;
 							HashEntry<K,V> n = newTable[k];
 							newTable[k] = newHashEntry(keyp.hashnp.value());
 						}
 					}
 				}
 			}
 			 = newTable;
 			return reduce;
 		}

Remove; match on key only if value null, else match both.
 
 		V remove(Object keyint hashObject valueboolean refRemove) {
 			lock();
 			try {
 				if (!refRemove)
 				int c =  - 1;
 				HashEntry<K,V>[] tab = ;
 				int index = hash & (tab.length - 1);
 				HashEntry<K,V> first = tab[index];
 				HashEntry<K,V> e = first;
 				// a ref remove operation compares the Reference instance
 				while (e != null && key != e.keyRef
 						&& (refRemove || hash != e.hash || !keyEq(keye.key())))
 					e = e.next;
 
 				V oldValue = null;
 				if (e != null) {
 					V v = e.value();
 					if (value == null || value.equals(v)) {
 						oldValue = v;
 						// All entries following removed node can stay
 						// in list, but all preceding ones need to be
 						// cloned.
 						HashEntry<K,V> newFirst = e.next;
 						for (HashEntry<K,V> p = firstp != ep = p.next) {
 							K pKey = p.key();
 							if (pKey == null) { // Skip GC'd keys
 								c--;
 								continue;
 							}
 
 							newFirst = newHashEntry(pKeyp.hashnewFirstp.value());
 						}
 						tab[index] = newFirst;
 						 = c// write-volatile
 					}
 				}
 				return oldValue;
 			} finally {
 				unlock();
 			}
 		}
 
 		final void removeStale() {
 			while ((ref = (KeyReference.poll()) != null) {
 				remove(ref.keyRef(), ref.keyHash(), nulltrue);
 			}
 		}
 
 		void clear() {
 			if ( != 0) {
 				lock();
 				try {
 					HashEntry<K,V>[] tab = ;
 					for (int i = 0; i < tab.length ; i++)
 						tab[i] = null;
 					// replace the reference queue to avoid unnecessary stale cleanups
 					 = 0; // write-volatile
 				} finally {
 					unlock();
 				}
 			}
 		}
 	}
 
 
 
 	/* ---------------- Public operations -------------- */

Creates a new, empty map with the specified initial capacity, reference types, load factor and concurrency level. Behavioral changing options such as ConcurrentReferenceHashMap.Option.IDENTITY_COMPARISONS can also be specified.

Parameters:
initialCapacity the initial capacity. The implementation performs internal sizing to accommodate this many elements.
loadFactor the load factor threshold, used to control resizing. Resizing may be performed when the average number of elements per bin exceeds this threshold.
concurrencyLevel the estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.
keyType the reference type to use for keys
valueType the reference type to use for values
options the behavioral options
Throws:
java.lang.IllegalArgumentException if the initial capacity is negative or the load factor or concurrencyLevel are nonpositive.
 
 	public ConcurrentReferenceHashMap(int initialCapacity,
 									  float loadFactorint concurrencyLevel,
 									  ReferenceType keyTypeReferenceType valueType,
 									  EnumSet<Optionoptions) {
 		if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
 			throw new IllegalArgumentException();
 
 		if (concurrencyLevel > )
 			concurrencyLevel = ;
 
 		// Find power-of-two sizes best matching arguments
 		int sshift = 0;
 		int ssize = 1;
 		while (ssize < concurrencyLevel) {
 			++sshift;
 			ssize <<= 1;
 		}
 		 = 32 - sshift;
 		 = ssize - 1;
 		this. = Segment.newArray(ssize);
 
 		if (initialCapacity > )
 			initialCapacity = ;
 		int c = initialCapacity / ssize;
 		if (c * ssize < initialCapacity)
 			++c;
 		int cap = 1;
 		while (cap < c)
 			cap <<= 1;
 
 		 = options != null && options.contains(.);
 
 		for (int i = 0; i < this..length; ++i)
 			this.[i] = new Segment<K,V>(caploadFactor,
 					keyTypevalueType);
 	}

Creates a new, empty map with the specified initial capacity, load factor and concurrency level.

Parameters:
initialCapacity the initial capacity. The implementation performs internal sizing to accommodate this many elements.
loadFactor the load factor threshold, used to control resizing. Resizing may be performed when the average number of elements per bin exceeds this threshold.
concurrencyLevel the estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.
Throws:
java.lang.IllegalArgumentException if the initial capacity is negative or the load factor or concurrencyLevel are nonpositive.
 
 	public ConcurrentReferenceHashMap(int initialCapacity,
 									  float loadFactorint concurrencyLevel) {
 		this(initialCapacityloadFactorconcurrencyLevel,
 	}

Creates a new, empty map with the specified initial capacity and load factor and with the default reference types (weak keys, strong values), and concurrencyLevel (16).

Parameters:
initialCapacity The implementation performs internal sizing to accommodate this many elements.
loadFactor the load factor threshold, used to control resizing. Resizing may be performed when the average number of elements per bin exceeds this threshold.
Throws:
java.lang.IllegalArgumentException if the initial capacity of elements is negative or the load factor is nonpositive
Since:
1.6
 
 	public ConcurrentReferenceHashMap(int initialCapacityfloat loadFactor) {
 		this(initialCapacityloadFactor);
 	}


Creates a new, empty map with the specified initial capacity, reference types and with default load factor (0.75) and concurrencyLevel (16).

Parameters:
initialCapacity the initial capacity. The implementation performs internal sizing to accommodate this many elements.
keyType the reference type to use for keys
valueType the reference type to use for values
Throws:
java.lang.IllegalArgumentException if the initial capacity of elements is negative.
 
 	public ConcurrentReferenceHashMap(int initialCapacity,
 									  ReferenceType keyTypeReferenceType valueType) {
 				keyTypevalueTypenull);
 	}

Creates a new, empty map with the specified initial capacity, and with default reference types (weak keys, strong values), load factor (0.75) and concurrencyLevel (16).

Parameters:
initialCapacity the initial capacity. The implementation performs internal sizing to accommodate this many elements.
Throws:
java.lang.IllegalArgumentException if the initial capacity of elements is negative.
 
 	public ConcurrentReferenceHashMap(int initialCapacity) {
 	}

Creates a new, empty map with a default initial capacity (16), reference types (weak keys, strong values), default load factor (0.75) and concurrencyLevel (16).
 
	}

Creates a new map with the same mappings as the given map. The map is created with a capacity of 1.5 times the number of mappings in the given map or 16 (whichever is greater), and a default load factor (0.75) and concurrencyLevel (16).

Parameters:
m the map
	public ConcurrentReferenceHashMap(Map<? extends K, ? extends V> m) {
		this(Math.max((int) (m.size() / ) + 1,
	}

Returns true if this map contains no key-value mappings.

Returns:
true if this map contains no key-value mappings
	public boolean isEmpty() {
		final Segment<K,V>[] segments = this.;
		/*
				 * We keep track of per-segment modCounts to avoid ABA
				 * problems in which an element in one segment was added and
				 * in another removed during traversal, in which case the
				 * table was never actually empty at any point. Note the
				 * similar use of modCounts in the size() and containsValue()
				 * methods, which are the only other methods also susceptible
				 * to ABA problems.
				 */
		int[] mc = new int[segments.length];
		int mcsum = 0;
		for (int i = 0; i < segments.length; ++i) {
			if (segments[i]. != 0)
				return false;
			else
				mcsum += mc[i] = segments[i].;
		// If mcsum happens to be zero, then we know we got a snapshot
		// before any modifications at all were made.  This is
		// probably common enough to bother tracking.
		if (mcsum != 0) {
			for (int i = 0; i < segments.length; ++i) {
				if (segments[i]. != 0 ||
						mc[i] != segments[i].)
					return false;
		return true;
	}

Returns the number of key-value mappings in this map. If the map contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.

Returns:
the number of key-value mappings in this map
	public int size() {
		final Segment<K,V>[] segments = this.;
		long sum = 0;
		long check = 0;
		int[] mc = new int[segments.length];
		// Try a few times to get accurate count. On failure due to
		// continuous async changes in table, resort to locking.
		for (int k = 0; k < ; ++k) {
			check = 0;
			sum = 0;
			int mcsum = 0;
			for (int i = 0; i < segments.length; ++i) {
				sum += segments[i].;
				mcsum += mc[i] = segments[i].;
			if (mcsum != 0) {
				for (int i = 0; i < segments.length; ++i) {
					check += segments[i].;
					if (mc[i] != segments[i].) {
						check = -1; // force retry
						break;
			if (check == sum)
				break;
		if (check != sum) { // Resort to locking all segments
			sum = 0;
			for (int i = 0; i < segments.length; ++i)
				segments[i].lock();
			for (int i = 0; i < segments.length; ++i)
				sum += segments[i].;
			for (int i = 0; i < segments.length; ++i)
				segments[i].unlock();
		if (sum > .)
		else
			return (int)sum;
	}

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

More formally, if this map contains a mapping from a key k to a value v such that key.equals(k), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

Throws:
java.lang.NullPointerException if the specified key is null
	public V get(Object key) {
		int hash = hashOf(key);
		return segmentFor(hash).get(keyhash);
	}

Tests if the specified object is a key in this table.

Parameters:
key possible key
Returns:
true if and only if the specified object is a key in this table, as determined by the equals method; false otherwise.
Throws:
java.lang.NullPointerException if the specified key is null
	public boolean containsKey(Object key) {
		int hash = hashOf(key);
		return segmentFor(hash).containsKey(keyhash);
	}

Returns true if this map maps one or more keys to the specified value. Note: This method requires a full internal traversal of the hash table, and so is much slower than method containsKey.

Parameters:
value value whose presence in this map is to be tested
Returns:
true if this map maps one or more keys to the specified value
Throws:
java.lang.NullPointerException if the specified value is null
	public boolean containsValue(Object value) {
		if (value == null)
			throw new NullPointerException();
		// See explanation of modCount use above
		final Segment<K,V>[] segments = this.;
		int[] mc = new int[segments.length];
		// Try a few times without locking
		for (int k = 0; k < ; ++k) {
			int mcsum = 0;
			for (int i = 0; i < segments.length; ++i) {
				mcsum += mc[i] = segments[i].;
				if (segments[i].containsValue(value))
					return true;
			boolean cleanSweep = true;
			if (mcsum != 0) {
				for (int i = 0; i < segments.length; ++i) {
					if (mc[i] != segments[i].) {
						cleanSweep = false;
						break;
			if (cleanSweep)
				return false;
		// Resort to locking all segments
		for (int i = 0; i < segments.length; ++i)
			segments[i].lock();
		boolean found = false;
		try {
			for (int i = 0; i < segments.length; ++i) {
				if (segments[i].containsValue(value)) {
					found = true;
					break;
finally {
			for (int i = 0; i < segments.length; ++i)
				segments[i].unlock();
		return found;
	}

Legacy method testing if some key maps into the specified value in this table. This method is identical in functionality to containsValue(java.lang.Object), and exists solely to ensure full compatibility with class java.util.Hashtable, which supported this method prior to introduction of the Java Collections framework.

Parameters:
value a value to search for
Returns:
true if and only if some key maps to the value argument in this table as determined by the equals method; false otherwise
Throws:
java.lang.NullPointerException if the specified value is null
	public boolean contains(Object value) {
		return containsValue(value);
	}

Maps the specified key to the specified value in this table. Neither the key nor the value can be null.

The value can be retrieved by calling the get method with a key that is equal to the original key.

Parameters:
key key with which the specified value is to be associated
value value to be associated with the specified key
Returns:
the previous value associated with key, or null if there was no mapping for key
Throws:
java.lang.NullPointerException if the specified key or value is null
	public V put(K key, V value) {
		if (value == null)
			throw new NullPointerException();
		int hash = hashOf(key);
		return segmentFor(hash).put(keyhashvaluefalse);
	}

Returns:
the previous value associated with the specified key, or null if there was no mapping for the key
Throws:
java.lang.NullPointerException if the specified key or value is null
	public V putIfAbsent(K key, V value) {
		if (value == null)
			throw new NullPointerException();
		int hash = hashOf(key);
		return segmentFor(hash).put(keyhashvaluetrue);
	}

Copies all of the mappings from the specified map to this one. These mappings replace any mappings that this map had for any of the keys currently in the specified map.

Parameters:
m mappings to be stored in this map
	public void putAll(Map<? extends K, ? extends V> m) {
		for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
			put(e.getKey(), e.getValue());
	}

Removes the key (and its corresponding value) from this map. This method does nothing if the key is not in the map.

Parameters:
key the key that needs to be removed
Returns:
the previous value associated with key, or null if there was no mapping for key
Throws:
java.lang.NullPointerException if the specified key is null
	public V remove(Object key) {
		int hash = hashOf(key);
		return segmentFor(hash).remove(keyhashnullfalse);
	}

Throws:
java.lang.NullPointerException if the specified key is null
	public boolean remove(Object keyObject value) {
		int hash = hashOf(key);
		if (value == null)
			return false;
		return segmentFor(hash).remove(keyhashvaluefalse) != null;
	}

Throws:
java.lang.NullPointerException if any of the arguments are null
	public boolean replace(K key, V oldValue, V newValue) {
		if (oldValue == null || newValue == null)
			throw new NullPointerException();
		int hash = hashOf(key);
		return segmentFor(hash).replace(keyhasholdValuenewValue);
	}

Returns:
the previous value associated with the specified key, or null if there was no mapping for the key
Throws:
java.lang.NullPointerException if the specified key or value is null
	public V replace(K key, V value) {
		if (value == null)
			throw new NullPointerException();
		int hash = hashOf(key);
		return segmentFor(hash).replace(keyhashvalue);
	}

Removes all of the mappings from this map.
	public void clear() {
		for (int i = 0; i < .; ++i)
	}

Removes any stale entries whose keys have been finalized. Use of this method is normally not necessary since stale entries are automatically removed lazily, when blocking operations are required. However, there are some cases where this operation should be performed eagerly, such as cleaning up old references to a ClassLoader in a multi-classloader environment. Note: this method will acquire locks, one at a time, across all segments of this table, so if it is to be used, it should be used sparingly.
	public void purgeStaleEntries() {
		for (int i = 0; i < .; ++i)
	}


Returns a java.util.Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

The view's iterator is a "weakly consistent" iterator that will never throw java.util.ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

	public Set<K> keySet() {
		Set<K> ks = ;
		return (ks != null) ? ks : ( = new KeySet());
	}

Returns a java.util.Collection view of the values contained in this map. The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa. The collection supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Collection.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

The view's iterator is a "weakly consistent" iterator that will never throw java.util.ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

	public Collection<V> values() {
		Collection<V> vs = ;
		return (vs != null) ? vs : ( = new Values());
	}

Returns a java.util.Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

The view's iterator is a "weakly consistent" iterator that will never throw java.util.ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

	public Set<Map.Entry<K,V>> entrySet() {
		Set<Map.Entry<K,V>> es = ;
		return (es != null) ? es : ( = new EntrySet());
	}

Returns an enumeration of the keys in this table.

Returns:
an enumeration of the keys in this table
See also:
keySet()
	public Enumeration<K> keys() {
		return new KeyIterator();
	}

Returns an enumeration of the values in this table.

Returns:
an enumeration of the values in this table
See also:
values()
	public Enumeration<V> elements() {
		return new ValueIterator();
	/* ---------------- Iterator Support -------------- */
	abstract class HashIterator {
		HashEntry<K,V>[] currentTable;
currentKey// Strong reference to weak key (prevents gc)
		public boolean hasMoreElements() { return hasNext(); }
		final void advance() {
			if ( != null && ( = .) != null)
				return;
			while ( >= 0) {
				if ( ( = [--]) != null)
					return;
			while ( >= 0) {
				if (seg.count != 0) {
					 = seg.table;
					for (int j = . - 1; j >= 0; --j) {
						if ( ( = [j]) != null) {
							 = j - 1;
							return;
		public boolean hasNext() {
			while ( != null) {
				if (.key() != null)
					return true;
			return false;
			do {
				if ( == null)
while ( == null); // Skip GC'd keys
		public void remove() {
			if ( == null)
			 = null;
	final class KeyIterator
			implements Iterator<K>, Enumeration<K>
		public K next()        { return super.nextEntry().key(); }
		public K nextElement() { return super.nextEntry().key(); }
	final class ValueIterator
			implements Iterator<V>, Enumeration<V>
		public V next()        { return super.nextEntry().value(); }
		public V nextElement() { return super.nextEntry().value(); }
	/*
		  * This class is needed for JDK5 compatibility.
		  */
	static class SimpleEntry<K, V> implements Entry<K, V>,
		private static final long serialVersionUID = -8499721149061103585L;
		private final K key;
		private V value;
		public SimpleEntry(K key, V value) {
			this. = key;
			this. = value;
		public SimpleEntry(Entry<? extends K, ? extends V> entry) {