ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java (file contents):
Revision 1.82 by jsr166, Mon Aug 22 03:05:49 2005 UTC vs.
Revision 1.92 by dl, Sat Dec 2 20:55:01 2006 UTC

# Line 62 | Line 62 | import java.io.ObjectOutputStream;
62   * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
63   *
64   * <p>This class is a member of the
65 < * <a href="{@docRoot}/../guide/collections/index.html">
65 > * <a href="{@docRoot}/../technotes/guides/collections/index.html">
66   * Java Collections Framework</a>.
67   *
68   * @since 1.5
# Line 146 | Line 146 | public class ConcurrentHashMap<K, V> ext
146      /* ---------------- Small Utilities -------------- */
147  
148      /**
149 <     * Returns a hash code for non-null Object x.
150 <     * Uses the same hash code spreader as most other java.util hash tables.
151 <     * @param x the object serving as a key
152 <     * @return the hash code
153 <     */
154 <    static int hash(Object x) {
155 <        int h = x.hashCode();
156 <        h += ~(h << 9);
157 <        h ^=  (h >>> 14);
158 <        h +=  (h << 4);
159 <        h ^=  (h >>> 10);
149 >     * Applies a supplemental hash function to a given hashCode, which
150 >     * defends against poor quality hash functions.  This is critical
151 >     * because ConcurrentHashMap uses power-of-two length hash tables,
152 >     * that otherwise encounter collisions for hashCodes that do not
153 >     * differ in lower bits.
154 >     */
155 >    private static int hash(int h) {
156 >        // Spread bits to regularize both segment and index locations,
157 >        // using variant of Jenkins's shift-based hash.
158 >        h += ~(h << 13);
159 >        h ^= h >>> 7;
160 >        h += h << 3;
161 >        h ^= h >>> 17;
162 >        h += h << 5;
163          return h;
164      }
165  
# Line 750 | Line 753 | public class ConcurrentHashMap<K, V> ext
753      }
754  
755      /**
756 <     * Returns the value to which this map maps the specified key, or
757 <     * <tt>null</tt> if the map contains no mapping for the key.
756 >     * Returns the value to which the specified key is mapped,
757 >     * or {@code null} if this map contains no mapping for the key.
758 >     *
759 >     * <p>More formally, if this map contains a mapping from a key
760 >     * {@code k} to a value {@code v} such that {@code key.equals(k)},
761 >     * then this method returns {@code v}; otherwise it returns
762 >     * {@code null}.  (There can be at most one such mapping.)
763       *
756     * @param key key whose associated value is to be returned
757     * @return the value to which this map maps the specified key, or
758     *         <tt>null</tt> if the map contains no mapping for the key
764       * @throws NullPointerException if the specified key is null
765       */
766      public V get(Object key) {
767 <        int hash = hash(key); // throws NullPointerException if key null
767 >        int hash = hash(key.hashCode());
768          return segmentFor(hash).get(key, hash);
769      }
770  
# Line 773 | Line 778 | public class ConcurrentHashMap<K, V> ext
778       * @throws NullPointerException if the specified key is null
779       */
780      public boolean containsKey(Object key) {
781 <        int hash = hash(key); // throws NullPointerException if key null
781 >        int hash = hash(key.hashCode());
782          return segmentFor(hash).containsKey(key, hash);
783      }
784  
# Line 873 | Line 878 | public class ConcurrentHashMap<K, V> ext
878      public V put(K key, V value) {
879          if (value == null)
880              throw new NullPointerException();
881 <        int hash = hash(key);
881 >        int hash = hash(key.hashCode());
882          return segmentFor(hash).put(key, hash, value, false);
883      }
884  
# Line 887 | Line 892 | public class ConcurrentHashMap<K, V> ext
892      public V putIfAbsent(K key, V value) {
893          if (value == null)
894              throw new NullPointerException();
895 <        int hash = hash(key);
895 >        int hash = hash(key.hashCode());
896          return segmentFor(hash).put(key, hash, value, true);
897      }
898  
# Line 899 | Line 904 | public class ConcurrentHashMap<K, V> ext
904       * @param m mappings to be stored in this map
905       */
906      public void putAll(Map<? extends K, ? extends V> m) {
907 <        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> it = (Iterator<? extends Map.Entry<? extends K, ? extends V>>) m.entrySet().iterator(); it.hasNext(); ) {
903 <            Entry<? extends K, ? extends V> e = it.next();
907 >        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
908              put(e.getKey(), e.getValue());
905        }
909      }
910  
911      /**
# Line 911 | Line 914 | public class ConcurrentHashMap<K, V> ext
914       *
915       * @param  key the key that needs to be removed
916       * @return the previous value associated with <tt>key</tt>, or
917 <     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
917 >     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
918       * @throws NullPointerException if the specified key is null
919       */
920      public V remove(Object key) {
921 <        int hash = hash(key);
921 >        int hash = hash(key.hashCode());
922          return segmentFor(hash).remove(key, hash, null);
923      }
924  
# Line 925 | Line 928 | public class ConcurrentHashMap<K, V> ext
928       * @throws NullPointerException if the specified key is null
929       */
930      public boolean remove(Object key, Object value) {
931 +        int hash = hash(key.hashCode());
932          if (value == null)
933              return false;
930        int hash = hash(key);
934          return segmentFor(hash).remove(key, hash, value) != null;
935      }
936  
# Line 939 | Line 942 | public class ConcurrentHashMap<K, V> ext
942      public boolean replace(K key, V oldValue, V newValue) {
943          if (oldValue == null || newValue == null)
944              throw new NullPointerException();
945 <        int hash = hash(key);
945 >        int hash = hash(key.hashCode());
946          return segmentFor(hash).replace(key, hash, oldValue, newValue);
947      }
948  
# Line 953 | Line 956 | public class ConcurrentHashMap<K, V> ext
956      public V replace(K key, V value) {
957          if (value == null)
958              throw new NullPointerException();
959 <        int hash = hash(key);
959 >        int hash = hash(key.hashCode());
960          return segmentFor(hash).replace(key, hash, value);
961      }
962  
# Line 1126 | Line 1129 | public class ConcurrentHashMap<K, V> ext
1129       * Custom Entry class used by EntryIterator.next(), that relays
1130       * setValue changes to the underlying map.
1131       */
1132 <    static final class WriteThroughEntry<K,V>
1132 >    final class WriteThroughEntry
1133          extends AbstractMap.SimpleEntry<K,V>
1134      {
1135 <        private final ConcurrentHashMap<K,V> map;
1133 <        WriteThroughEntry(ConcurrentHashMap map, K k, V v) {
1135 >        WriteThroughEntry(K k, V v) {
1136              super(k,v);
1135            this.map = map;
1137          }
1138  
1139          /**
# Line 1147 | Line 1148 | public class ConcurrentHashMap<K, V> ext
1148          public V setValue(V value) {
1149              if (value == null) throw new NullPointerException();
1150              V v = super.setValue(value);
1151 <            map.put(getKey(), value);
1151 >            ConcurrentHashMap.this.put(getKey(), value);
1152              return v;
1153          }
1154      }
# Line 1158 | Line 1159 | public class ConcurrentHashMap<K, V> ext
1159      {
1160          public Map.Entry<K,V> next() {
1161              HashEntry<K,V> e = super.nextEntry();
1162 <            return new WriteThroughEntry<K,V>(ConcurrentHashMap.this,
1162 <                                              e.key, e.value);
1162 >            return new WriteThroughEntry(e.key, e.value);
1163          }
1164      }
1165  
# Line 1179 | Line 1179 | public class ConcurrentHashMap<K, V> ext
1179          public void clear() {
1180              ConcurrentHashMap.this.clear();
1181          }
1182        public Object[] toArray() {
1183            Collection<K> c = new ArrayList<K>(size());
1184            for (K k : this)
1185                c.add(k);
1186            return c.toArray();
1187        }
1188        public <T> T[] toArray(T[] a) {
1189            Collection<K> c = new ArrayList<K>();
1190            for (K k : this)
1191                c.add(k);
1192            return c.toArray(a);
1193        }
1182      }
1183  
1184      final class Values extends AbstractCollection<V> {
# Line 1206 | Line 1194 | public class ConcurrentHashMap<K, V> ext
1194          public void clear() {
1195              ConcurrentHashMap.this.clear();
1196          }
1209        public Object[] toArray() {
1210            Collection<V> c = new ArrayList<V>(size());
1211            for (V v : this)
1212                c.add(v);
1213            return c.toArray();
1214        }
1215        public <T> T[] toArray(T[] a) {
1216            Collection<V> c = new ArrayList<V>(size());
1217            for (V v : this)
1218                c.add(v);
1219            return c.toArray(a);
1220        }
1197      }
1198  
1199      final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
# Line 1243 | Line 1219 | public class ConcurrentHashMap<K, V> ext
1219          public void clear() {
1220              ConcurrentHashMap.this.clear();
1221          }
1246        public Object[] toArray() {
1247            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
1248            for (Map.Entry<K,V> e : this)
1249                c.add(e);
1250            return c.toArray();
1251        }
1252        public <T> T[] toArray(T[] a) {
1253            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
1254            for (Map.Entry<K,V> e : this)
1255                c.add(e);
1256            return c.toArray(a);
1257        }
1258
1222      }
1223  
1224      /* ---------------- Serialization Support -------------- */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines