Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
What is the most efficient Java Collections library? A few years ago, I did a lot of Java and had the impression back then that trove is the best (most efficient) Java Collections implementation. But when I read the answers to the question "Most useful free Java libraries?" I noticed that trove is hardly mentioned. So which Java Collections library is best now? UPDATE: To clarify, I mostly w...
I have a Map which is to be modified by several threads concurrently. There seem to be three different synchronized Map implementations in the Java API: Hashtable Collections.synchronizedMap(Map) ConcurrentHashMap From what I understand, Hashtable is an old implementation (extending the obsolete Dictionary class), which has been adapted later to fit the Map interface. While it is synchron...
Please don't say EHCache or OSCache, etc. Assume for purposes of this question that I want to implement my own using just the SDK (learning by doing). Given that the cache will be used in a multithreaded environment, which datastructures would you use? I've already implemented one using LinkedHashMap and Collections#synchronizedMap, but I'm curious if any of the new concurrent collections would...
I've recently been learning about various libraries for concurrency in Java such as ConcurrentHashMap and the lovely non blocking one from Cliff Click I don't know much about Scala but I've heard good things about the recent parallel collections library. I'd like to know what are some major advantages that this library would give over Java based libraries?
Is ConcurrentHashMap.get() guaranteed to see a previous ConcurrentHashMap.put() by different thread? My expectation is that is is, and reading the JavaDocs seems to indicate so, but I am 99% convinced that reality is different. On my production server the below seems to be happening. (I've caught it with logging.) Pseudo code example: static final ConcurrentHashMap map = new ConcurrentHash...
Is the following code set up to correctly synchronize the calls on synchronizedMap? public class MyClass { private static Map<String, List<String>> synchronizedMap = Collections.synchronizedMap(new HashMap<String, List<String>>()); public void doWork(String key) { List<String> values = null; while ((values = synchronizedMap.remove(key)) != null) { ...
How does the Boost Thread libraries compare against the java.util.concurrent libraries? Performance is critical and so I would prefer to stay with C++ (although Java is a lot faster these days). Given that I have to code in C++, what libraries exist to make threading easy and less error prone. I have heard recently that as of JDK 1.5, the Java memory model was changed to fix some concurrency...
I need to gather some statistics in my software and i am trying to make it fast and correct, which is not easy (for me!) first my code so far with two classes, a StatsService and a StatsHarvester public class StatsService { private Map<String, Long> stats = new HashMap<String, Long>(1000); public void notify ( String key ) { Long value = 1l; synchronized (stats) ...
I have a Hashmap that, for speed reasons, I would like to not require locking on. Will updating it and accessing it at the same time cause any issues, assuming I don't mind stale data? My accesses are gets, not iterating through it, and deletes are part of the updates.
In javadoc for ConcurrentHashMap is the following: 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...
In Java, ConcurrentHashMap is there for better multithreading solution. Then when should I use ConcurrentSkipListMap? Is it a redundancy? Does multithreading aspects between these two are common?
I have a large array to be accessed by multiple thread. Single lock is not efficient enough.Is there a range lock class in java or scala?
Note that I'm not actually doing anything with a database here, so ORM tools are probably not what I'm looking for. I want to have some containers that each hold a number of objects, with all objects in one container being of the same class. The container should show some of the behaviour of a database table, namely: allow one of the object's fields to be used as a unique key, i. e. other ob...
I've got some questions about Java's assigment. Strings I've got a class: public class Test { private String s; public synchronized void setS(String str){ s = s + " - " + str; } public String getS(){ return s; } } I'm using "synchronized" in my setter, and avoiding it in my getter, because in my app, there are a tons of data gettings, and very few settings. Settings must be sy...
So, there is a concurrent hashmap in Java, the advantage of which is not to lock down the whole hash table, but only portions of it. I was wondering whether there was such a construction for arrays. Particularly when an array is being resized locking down the whole array is not desirable, especially in real time applications. Anything out there?
How is the performance of ConcurrentHashMap compared to HashMap, especially .get() operation (I'm especially interested for the case of only few items, in the range between maybe 0-5000)? Is there any reason not to use ConcurrentHashMap instead of HashMap? (I know that null values aren't allowed) Update just to clarify, obviously the performance in case of actual concurrent access will suff...
The JavaDoc of ConcurrentHashMap says this: Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value. My question: why? 2nd question: why doesn't Hashtable allow null? I've used a lot of HashMaps for storing data. But when changing to ConcurrentHashMap I got several times into trouble because of NullPointerExceptions.
To recap for those .NET gurus who might not know the Java API: ConcurrentHashMap in Java has atomic methods (i.e. require no external locking) for common Map modification operations such as: putIfAbsent(K key, V value) remove(Object key, Object value) replace(K key, V value) It also allows iteration over the keyset without locking (it takes a copy at the start of iteration) and get() operat...
I hope this isn't too silly a question... I have code similar to the following in my project: public class ConfigStore { public static class Config { public final String setting1; public final String setting2; public final String setting3; public Config(String setting1, String setting2, String setting3) { this.setting1 = setting1; ...
The JDK ships with CopyOnWrite collections for set and list, but none for Map and I've often lamented this fact. I know there are other collections implementations out there that have them, but it would be nice if one shipped as standard. It seems like an obvious omission and I'm wondering if there was a good reason for it. Anyone any idea why this was left out?
The project I am working on requires a whole bunch of queries towards a database. In principle there are two types of queries I am using: read from excel file, check for a couple of parameters and do a query for hits in the database. These hits are then registered as a series of custom classes. Any hit may (and most likely will) occur more than once so this part of the code checks and updates...
   /*
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    *
    * This code is free software; you can redistribute it and/or modify it
    * under the terms of the GNU General Public License version 2 only, as
    * published by the Free Software Foundation.  Sun designates this
    * particular file as subject to the "Classpath" exception as provided
    * by Sun in the LICENSE file that accompanied this code.
    *
   * This code 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 General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  /*
   * This file is available under and governed by the GNU General Public
   * License version 2 only, as published by the Free Software Foundation.
   * However, the following notice accompanied the original version of this
   * file:
   *
   * 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 java.util.concurrent;
  import java.util.*;
A hash table supporting full concurrency of retrievals and adjustable expected concurrency for updates. 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
Since:
1.5
 
 public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
         implements 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.
      */
 
     /* ---------------- 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 ConcurrentHashMap 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 >>> ) & ];
     }
 
     /* ---------------- Inner Classes -------------- */

    
ConcurrentHashMap 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 K key;
         final int hash;
         volatile V value;
         final HashEntry<K,V> next;
 
         HashEntry(K keyint hashHashEntry<K,V> next, V value) {
             this. = key;
             this. = hash;
             this. = next;
             this. = value;
         }
 
         @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;
 
         Segment(int initialCapacityfloat lf) {
              = lf;
             setTable(HashEntry.<K,V>newArray(initialCapacity));
         }
 
         @SuppressWarnings("unchecked")
         static final <K,V> Segment<K,V>[] newArray(int i) {
             return new Segment[i];
         }

        
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)];
         }

        
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.
 
         V readValueUnderLock(HashEntry<K,V> e) {
             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 && key.equals(e.key)) {
                         V v = e.value;
                         if (v != null)
                             return v;
                         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 && key.equals(e.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) {
                         V v = e.value;
                         if (v == null// recheck
                             v = readValueUnderLock(e);
                         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 || !key.equals(e.key)))
                     e = e.next;
 
                 boolean replaced = false;
                 if (e != null && oldValue.equals(e.value)) {
                     replaced = true;
                     e.value = 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 || !key.equals(e.key)))
                     e = e.next;
 
                 V oldValue = null;
                 if (e != null) {
                     oldValue = e.value;
                     e.value = newValue;
                 }
                 return oldValue;
             } finally {
                 unlock();
             }
         }
 
 
         V put(K keyint hash, V valueboolean onlyIfAbsent) {
             lock();
             try {
                 int c = ;
                 if (c++ > // ensure capacity
                     rehash();
                 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 || !key.equals(e.key)))
                     e = e.next;
 
                 V oldValue;
                 if (e != null) {
                     oldValue = e.value;
                     if (!onlyIfAbsent)
                         e.value = value;
                 }
                 else {
                     oldValue = null;
                     ++;
                     tab[index] = new HashEntry<K,V>(keyhashfirstvalue);
                      = c// write-volatile
                 }
                 return oldValue;
             } finally {
                 unlock();
             }
         }
 
         void rehash() {
             HashEntry<K,V>[] oldTable = ;
             int oldCapacity = oldTable.length;
             if (oldCapacity >= )
                 return;
 
             /*
              * 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;
             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) {
                             int k = p.hash & sizeMask;
                             HashEntry<K,V> n = newTable[k];
                             newTable[k] = new HashEntry<K,V>(p.keyp.hash,
                                                              np.value);
                         }
                     }
                 }
             }
              = newTable;
         }

        
Remove; match on key only if value null, else match both.
 
         V remove(Object keyint hashObject value) {
             lock();
             try {
                 int c =  - 1;
                 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 || !key.equals(e.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)
                             newFirst = new HashEntry<K,V>(p.keyp.hash,
                                                           newFirstp.value);
                         tab[index] = newFirst;
                          = c// write-volatile
                     }
                 }
                 return oldValue;
             } finally {
                 unlock();
             }
         }
 
         void clear() {
             if ( != 0) {
                 lock();
                 try {
                     HashEntry<K,V>[] tab = ;
                     for (int i = 0; i < tab.length ; i++)
                         tab[i] = null;
                     ++;
                      = 0; // write-volatile
                 } finally {
                     unlock();
                 }
             }
         }
     }
 
 
 
     /* ---------------- Public operations -------------- */

    
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 ConcurrentHashMap(int initialCapacity,
                              float loadFactorint concurrencyLevel) {
         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;
 
         for (int i = 0; i < this..length; ++i)
             this.[i] = new Segment<K,V>(caploadFactor);
     }

    
Creates a new, empty map with the specified initial capacity and load factor and with the default 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 ConcurrentHashMap(int initialCapacityfloat loadFactor) {
         this(initialCapacityloadFactor);
     }

    
Creates a new, empty map with the specified initial capacity, 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.
Throws:
java.lang.IllegalArgumentException if the initial capacity of elements is negative.
 
     public ConcurrentHashMap(int initialCapacity) {
         this(initialCapacity);
     }

    
Creates a new, empty map with a default initial capacity (16), load factor (0.75) and concurrencyLevel (16).
 
     public ConcurrentHashMap() {
     }

    
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 ConcurrentHashMap(Map<? extends K, ? extends V> m) {
         this(Math.max((int) (m.size() / ) + 1,
                       ),
              );
         putAll(m);
     }

    
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 > .)
             return .;
         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 = hash(key.hashCode());
         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 = hash(key.hashCode());
         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 sum = 0;
             int mcsum = 0;
             for (int i = 0; i < segments.length; ++i) {
                 int c = segments[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) {
                     int c = segments[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 = hash(key.hashCode());
         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 = hash(key.hashCode());
         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 = hash(key.hashCode());
         return segmentFor(hash).remove(keyhashnull);
     }

    

Throws:
java.lang.NullPointerException if the specified key is null
 
     public boolean remove(Object keyObject value) {
         int hash = hash(key.hashCode());
         if (value == null)
             return false;
         return segmentFor(hash).remove(keyhashvalue) != 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 = hash(key.hashCode());
         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 = hash(key.hashCode());
         return segmentFor(hash).replace(keyhashvalue);
     }

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

    
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 {
        int nextSegmentIndex;
        int nextTableIndex;
        HashEntry<K,V>[] currentTable;
        HashEntry<K, V> nextEntry;
        HashEntry<K, V> lastReturned;
        HashIterator() {
             = . - 1;
             = -1;
            advance();
        }
        public boolean hasMoreElements() { return hasNext(); }
        final void advance() {
            if ( != null && ( = .) != null)
                return;
            while ( >= 0) {
                if ( ( = [--]) != null)
                    return;
            }
            while ( >= 0) {
                Segment<K,V> seg = [--];
                if (seg.count != 0) {
                     = seg.table;
                    for (int j = . - 1; j >= 0; --j) {
                        if ( ( = [j]) != null) {
                             = j - 1;
                            return;
                        }
                    }
                }
            }
        }
        public boolean hasNext() { return  != null; }
        HashEntry<K,V> nextEntry() {
            if ( == null)
                throw new NoSuchElementException();
             = ;
            advance();
            return ;
        }
        public void remove() {
            if ( == null)
                throw new IllegalStateException();
            ConcurrentHashMap.this.remove(.);
             = null;
        }
    }
    final class KeyIterator
        extends HashIterator
        implements Iterator<K>, Enumeration<K>
    {
        public K next()        { return super.nextEntry().; }
        public K nextElement() { return super.nextEntry().; }
    }
    final class ValueIterator
        extends HashIterator
        implements Iterator<V>, Enumeration<V>
    {
        public V next()        { return super.nextEntry().; }
        public V nextElement() { return super.nextEntry().; }
    }

    
Custom Entry class used by EntryIterator.next(), that relays setValue changes to the underlying map.
    final class WriteThroughEntry
        extends AbstractMap.SimpleEntry<K,V>
    {
        WriteThroughEntry(K k, V v) {
            super(k,v);
        }

        
Set our entry's value and write through to the map. The value to return is somewhat arbitrary here. Since a WriteThroughEntry does not necessarily track asynchronous changes, the most recent "previous" value could be different from what we return (or could even have been removed in which case the put will re-establish). We do not and cannot guarantee more.
        public V setValue(V value) {
            if (value == nullthrow new NullPointerException();
            V v = super.setValue(value);
            ConcurrentHashMap.this.put(getKey(), value);
            return v;
        }
    }
    final class EntryIterator
        extends HashIterator
        implements Iterator<Entry<K,V>>
    {
        public Map.Entry<K,V> next() {
            HashEntry<K,V> e = super.nextEntry();
            return new WriteThroughEntry(e.keye.value);
        }
    }
    final class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return new KeyIterator();
        }
        public int size() {
            return ConcurrentHashMap.this.size();
        }
        public boolean isEmpty() {
            return ConcurrentHashMap.this.isEmpty();
        }
        public boolean contains(Object o) {
            return ConcurrentHashMap.this.containsKey(o);
        }
        public boolean remove(Object o) {
            return ConcurrentHashMap.this.remove(o) != null;
        }
        public void clear() {
            ConcurrentHashMap.this.clear();
        }
    }
    final class Values extends AbstractCollection<V> {
        public Iterator<V> iterator() {
            return new ValueIterator();
        }
        public int size() {
            return ConcurrentHashMap.this.size();
        }
        public boolean isEmpty() {
            return ConcurrentHashMap.this.isEmpty();
        }
        public boolean contains(Object o) {
            return ConcurrentHashMap.this.containsValue(o);
        }
        public void clear() {
            ConcurrentHashMap.this.clear();
        }
    }
    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator();
        }
        public boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            V v = ConcurrentHashMap.this.get(e.getKey());
            return v != null && v.equals(e.getValue());
        }
        public boolean remove(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
        }
        public int size() {
            return ConcurrentHashMap.this.size();
        }
        public boolean isEmpty() {
            return ConcurrentHashMap.this.isEmpty();
        }
        public void clear() {
            ConcurrentHashMap.this.clear();
        }
    }
    /* ---------------- Serialization Support -------------- */

    
Save the state of the ConcurrentHashMap instance to a stream (i.e., serialize it).

Parameters:
s the stream
SerialData:
the key (Object) and value (Object) for each key-value mapping, followed by a null pair. The key-value mappings are emitted in no particular order.
    private void writeObject(java.io.ObjectOutputStream sthrows IOException  {
        s.defaultWriteObject();
        for (int k = 0; k < .; ++k) {
            Segment<K,V> seg = [k];
            seg.lock();
            try {
                HashEntry<K,V>[] tab = seg.table;
                for (int i = 0; i < tab.length; ++i) {
                    for (HashEntry<K,V> e = tab[i]; e != nulle = e.next) {
                        s.writeObject(e.key);
                        s.writeObject(e.value);
                    }
                }
            } finally {
                seg.unlock();
            }
        }
        s.writeObject(null);
        s.writeObject(null);
    }

    
Reconstitute the ConcurrentHashMap instance from a stream (i.e., deserialize it).

Parameters:
s the stream
    private void readObject(java.io.ObjectInputStream s)
        throws IOExceptionClassNotFoundException  {
        s.defaultReadObject();
        // Initialize each segment to be minimally sized, and let grow.
        for (int i = 0; i < .; ++i) {
            [i].setTable(new HashEntry[1]);
        }
        // Read the keys and values, and put the mappings in the table
        for (;;) {
            K key = (K) s.readObject();
            V value = (V) s.readObject();
            if (key == null)
                break;
            put(keyvalue);
        }
    }
New to GrepCode? Check out our FAQ X