/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain. Use, modify, and * redistribute this code in any way without acknowledgement. */ package java.util.concurrent; import java.util.*; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /** * A version of Hashtable supporting * concurrency for both retrievals and updates. * *
* * Iterators and Enumerations (i.e., those returned by * keySet().iterator(), entrySet().iterator(), values().iterator(), * keys(), and elements()) return elements reflecting the state of the * hash table at some point at or since the creation of the * iterator/enumeration. They will return at most one instance of * each element (via next()/nextElement()), but might or might not * reflect puts and removes that have been processed since * construction if the Iterator. They do not throw * ConcurrentModificationException. However, these iterators are * designed to be used by only one thread at a time. Passing an * iterator across multiple threads may lead to unpredictable traversal * if the table is being concurrently modified.
* * *
* * There is NOT any support for locking the entire table to * prevent updates. * *
*
**/
public class ConcurrentHashMap
*
* The value can be retrieved by calling the
*
* Note that this method is identical in functionality to containsValue,
* (which is part of the Map interface in the collections framework).
*
* @param value a value to search for.
* @return null
if the key is not mapped to any value in
* this table.
* @exception NullPointerException if the key is
* null
.
* @see #put(Object, Object)
*/
public V get(Object key) {
int hash = hash(key); // throws null pointer exception if key null
// Try first without locking...
Entrytrue
if and only if the specified object
* is a key in this table, as determined by the
* equals method; false
otherwise.
* @exception NullPointerException if the key is
* null
.
* @see #contains(Object)
*/
public boolean containsKey(Object key) {
return get(key) != null;
}
/**
* Maps the specified key
to the specified
* value
in this table. Neither the key nor the
* value can be null
. (Note that this policy is
* the same as for java.util.Hashtable, but unlike java.util.HashMap,
* which does accept nulls as valid keys and values.)get
method
* with a key that is equal to the original key.
*
* @param key the table key.
* @param value the value.
* @return the previous value of the specified key in this table,
* or null
if it did not have one.
* @exception NullPointerException if the key or value is
* null
.
* @see Object#equals(Object)
* @see #get(Object)
*/
public V put(K key, V value) {
if (value == null)
throw new NullPointerException();
int hash = hash(key);
Segment seg = segments[hash & SEGMENT_MASK];
int segcount;
Entrynull
if the key did not have a mapping.
* @exception NullPointerException if the key is
* null
.
*/
public V remove(Object key) {
return remove(key, null);
}
/**
* Removes the (key, value) pair from this
* table. This method does nothing if the key is not in the table,
* or if the key is associated with a different value. This method
* is needed by EntrySet.
*
* @param key the key that needs to be removed.
* @param value the associated value. If the value is null,
* it means "any value".
* @return the value to which the key had been mapped in this table,
* or null
if the key did not have a mapping.
* @exception NullPointerException if the key is
* null
.
*/
private V remove(Object key, V value) {
/*
Find the entry, then
1. Set value field to null, to force get() to retry
2. Rebuild the list without this entry.
All entries following removed node can stay in list, but
all preceeding ones need to be cloned. Traversals rely
on this strategy to ensure that elements will not be
repeated during iteration.
*/
int hash = hash(key);
Segment seg = segments[hash & SEGMENT_MASK];
seg.lock();
try {
Entrynull
.
*/
public boolean containsValue(Object value) {
if (value == null) throw new NullPointerException();
for (int s = 0; s < segments.length; ++s) {
Segment seg = segments[s];
EntrycontainsKey
* method.true
if and only if some key maps to the
* value
argument in this table as
* determined by the equals method;
* false
otherwise.
* @exception NullPointerException if the value is null
.
* @see #containsKey(Object)
* @see #containsValue(Object)
* @see Map
*/
public boolean contains(V value) {
return containsValue(value);
}
/**
* 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.
*
* @param t Mappings to be stored in this map.
*/
public void putAll(Map t) {
int n = t.size();
if (n == 0)
return;
// Expand enough to hold at least n elements without resizing.
// We can only resize table by factor of two at a time.
// It is faster to rehash with fewer elements, so do it now.
for(;;) {
Entrynull
.
*
**/
public V setValue(V value) {
if (value == null)
throw new NullPointerException();
V oldValue = this.value;
this.value = value;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
return (key.equals(e.getKey()) && value.equals(e.getValue()));
}
public int hashCode() {
return key.hashCode() ^ value.hashCode();
}
public String toString() {
return key + "=" + value;
}
}
private abstract class HashIterator