/[classpath]/classpath/java/util/HashMap.java
ViewVC logotype

Diff of /classpath/java/util/HashMap.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.16 by bryce, Tue Oct 16 05:24:14 2001 UTC revision 1.17 by ericb, Thu Oct 25 07:34:19 2001 UTC
# Line 53  import java.io.ObjectOutputStream; Line 53  import java.io.ObjectOutputStream;
53   * <p>   * <p>
54   *   *
55   * Under ideal circumstances (no collisions), HashMap offers O(1)   * Under ideal circumstances (no collisions), HashMap offers O(1)
56   * performance on most operations (<pre>containsValue()</pre> is,   * performance on most operations (<code>containsValue()</code> is,
57   * of course, O(n)).  In the worst case (all keys map to the same   * of course, O(n)).  In the worst case (all keys map to the same
58   * hash code -- very unlikely), most operations are O(n).   * hash code -- very unlikely), most operations are O(n).
59   * <p>   * <p>
60   *   *
61   * HashMap is part of the JDK1.2 Collections API.  It differs from   * HashMap is part of the JDK1.2 Collections API.  It differs from
62   * Hashtable in that it accepts the null key and null values, and it   * Hashtable in that it accepts the null key and null values, and it
63   * does not support "Enumeration views."   * does not support "Enumeration views." Also, it is not synchronized;
64     * if you plan to use it in multiple threads, consider using:<br>
65     * <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
66   * <p>   * <p>
67   *   *
68   * The iterators are <i>fail-fast</i>, meaning that any structural   * The iterators are <i>fail-fast</i>, meaning that any structural
# Line 81  import java.io.ObjectOutputStream; Line 83  import java.io.ObjectOutputStream;
83   * @see IdentityHashMap   * @see IdentityHashMap
84   * @see Hashtable   * @see Hashtable
85   * @since 1.2   * @since 1.2
86     * @status updated to 1.4
87   */   */
88  public class HashMap extends AbstractMap  public class HashMap extends AbstractMap
89    implements Map, Cloneable, Serializable    implements Map, Cloneable, Serializable
# Line 88  public class HashMap extends AbstractMap Line 91  public class HashMap extends AbstractMap
91    /**    /**
92     * Default number of buckets. This is the value the JDK 1.3 uses. Some     * Default number of buckets. This is the value the JDK 1.3 uses. Some
93     * early documentation specified this value as 101. That is incorrect.     * early documentation specified this value as 101. That is incorrect.
94       * Package visible for use by HashSet.
95     */     */
96    static final int DEFAULT_CAPACITY = 11;    static final int DEFAULT_CAPACITY = 11;
97    
98    /**    /**
99     * The default load factor; this is explicitly specified by the spec.     * The default load factor; this is explicitly specified by the spec.
100       * Package visible for use by HashSet.
101     */     */
102    static final float DEFAULT_LOAD_FACTOR = 0.75f;    static final float DEFAULT_LOAD_FACTOR = 0.75f;
103    
   /** "enum" of iterator types. */  
   static final int KEYS = 0,  
                    VALUES = 1,  
                    ENTRIES = 2;  
   
104    /**    /**
105     * Compatible with JDK 1.2.     * Compatible with JDK 1.2.
106     */     */
# Line 108  public class HashMap extends AbstractMap Line 108  public class HashMap extends AbstractMap
108    
109    /**    /**
110     * The rounded product of the capacity and the load factor; when the number     * The rounded product of the capacity and the load factor; when the number
111     * of elements exceeds the threshold, the HashMap calls <pre>rehash()</pre>.     * of elements exceeds the threshold, the HashMap calls
112     * @serial     * <code>rehash()</code>.
113       * @serial the threshold for rehashing
114     */     */
115    int threshold;    private int threshold;
116    
117    /**    /**
118     * Load factor of this HashMap:  used in computing the threshold.     * Load factor of this HashMap:  used in computing the threshold.
119     * @serial     * Package visible for use by HashSet.
120       * @serial the load factor
121     */     */
122    final float loadFactor;    final float loadFactor;
123    
124    /**    /**
125     * Array containing the actual key-value mappings.     * Array containing the actual key-value mappings.
126       * Package visible for use by nested and subclasses.
127     */     */
128    transient HashEntry[] buckets;    transient HashEntry[] buckets;
129    
130    /**    /**
131     * Counts the number of modifications this HashMap has undergone, used     * Counts the number of modifications this HashMap has undergone, used
132     * by Iterators to know when to throw ConcurrentModificationExceptions.     * by Iterators to know when to throw ConcurrentModificationExceptions.
133       * Package visible for use by nested and subclasses.
134     */     */
135    transient int modCount;    transient int modCount;
136    
137    /**    /**
138     * The size of this HashMap:  denotes the number of key-value pairs.     * The size of this HashMap:  denotes the number of key-value pairs.
139       * Package visible for use by nested and subclasses.
140     */     */
141    transient int size;    transient int size;
142    
143    /**    /**
144       * The cache for {@link #entrySet()}.
145       */
146      private transient Set entries;
147    
148      /**
149     * Class to represent an entry in the hash table. Holds a single key-value     * Class to represent an entry in the hash table. Holds a single key-value
150     * pair.  This is extended again in LinkedHashMap.  See {@link clone()}     * pair. Package visible for use by subclass.
151     * for why this must be Cloneable.     *
152       * @author Eric Blake <ebb9@email.byu.edu>
153     */     */
154    static class HashEntry extends BasicMapEntry implements Cloneable    static class HashEntry extends BasicMapEntry
155    {    {
156      /** The next entry in the linked list. */      /**
157         * The next entry in the linked list. Package visible for use by subclass.
158         */
159      HashEntry next;      HashEntry next;
160    
161      /**      /**
# Line 158  public class HashMap extends AbstractMap Line 171  public class HashMap extends AbstractMap
171      /**      /**
172       * Called when this entry is removed from the map. This version simply       * Called when this entry is removed from the map. This version simply
173       * returns the value, but in LinkedHashMap, it must also do bookkeeping.       * returns the value, but in LinkedHashMap, it must also do bookkeeping.
174       * @return the value of this key as it is removed.       *
175         * @return the value of this key as it is removed
176       */       */
177      Object cleanup()      Object cleanup()
178      {      {
# Line 182  public class HashMap extends AbstractMap Line 196  public class HashMap extends AbstractMap
196     *     *
197     * Every element in Map m will be put into this new HashMap.     * Every element in Map m will be put into this new HashMap.
198     *     *
199     * @param m a Map whose key / value pairs will be put into     * @param m a Map whose key / value pairs will be put into the new HashMap.
200     *          the new HashMap.  <b>NOTE: key / value pairs     *        <b>NOTE: key / value pairs are not cloned in this constructor.</b>
    *          are not cloned in this constructor.</b>  
201     * @throws NullPointerException if m is null     * @throws NullPointerException if m is null
202     */     */
203    public HashMap(Map m)    public HashMap(Map m)
# Line 197  public class HashMap extends AbstractMap Line 210  public class HashMap extends AbstractMap
210     * Construct a new HashMap with a specific inital capacity and     * Construct a new HashMap with a specific inital capacity and
211     * default load factor of 0.75.     * default load factor of 0.75.
212     *     *
213     * @param initialCapacity the initial capacity of this HashMap (>=0)     * @param initialCapacity the initial capacity of this HashMap (&gt;=0)
214     * @throws IllegalArgumentException if (initialCapacity < 0)     * @throws IllegalArgumentException if (initialCapacity &lt; 0)
215     */     */
216    public HashMap(int initialCapacity)    public HashMap(int initialCapacity)
217    {    {
# Line 208  public class HashMap extends AbstractMap Line 221  public class HashMap extends AbstractMap
221    /**    /**
222     * Construct a new HashMap with a specific inital capacity and load factor.     * Construct a new HashMap with a specific inital capacity and load factor.
223     *     *
224     * @param initialCapacity the initial capacity (>=0)     * @param initialCapacity the initial capacity (&gt;=0)
225     * @param loadFactor the load factor (>0, not NaN)     * @param loadFactor the load factor (&gt; 0, not NaN)
226     * @throws IllegalArgumentException if (initialCapacity < 0) ||     * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
227     *                                     ! (loadFactor > 0.0)     *                                     ! (loadFactor &gt; 0.0)
228     */     */
229    public HashMap(int initialCapacity, float loadFactor)    public HashMap(int initialCapacity, float loadFactor)
230    {    {
# Line 229  public class HashMap extends AbstractMap Line 242  public class HashMap extends AbstractMap
242    }    }
243    
244    /**    /**
245     * Returns the number of kay-value mappings currently in this Map     * Returns the number of kay-value mappings currently in this Map.
246       *
247     * @return the size     * @return the size
248     */     */
249    public int size()    public int size()
# Line 238  public class HashMap extends AbstractMap Line 252  public class HashMap extends AbstractMap
252    }    }
253    
254    /**    /**
255     * Returns true if there are no key-value mappings currently in this Map     * Returns true if there are no key-value mappings currently in this Map.
256       *
257     * @return <code>size() == 0</code>     * @return <code>size() == 0</code>
258     */     */
259    public boolean isEmpty()    public boolean isEmpty()
# Line 247  public class HashMap extends AbstractMap Line 262  public class HashMap extends AbstractMap
262    }    }
263    
264    /**    /**
265     * Returns true if this HashMap contains a value <pre>o</pre>, such that     * Return the value in this HashMap associated with the supplied key,
266     * <pre>o.equals(value)</pre>.     * or <code>null</code> if the key maps to nothing.  NOTE: Since the value
267       * could also be null, you must use containsKey to see if this key
268       * actually maps to something.
269     *     *
270     * @param value the value to search for in this HashMap     * @param key the key for which to fetch an associated value
271     * @return true if at least one key maps to the value     * @return what the key maps to, if present
272       * @see #put(Object, Object)
273       * @see #containsKey(Object)
274     */     */
275    public boolean containsValue(Object value)    public Object get(Object key)
276    {    {
277      for (int i = buckets.length - 1; i >= 0; i--)      int idx = hash(key);
278        HashEntry e = buckets[idx];
279        while (e != null)
280        {        {
281          HashEntry e = buckets[i];          if (equals(key, e.key))
282          while (e != null)            return e.value;
283            {          e = e.next;
             if (value == null ? e.value == null : value.equals(e.value))  
               return true;  
             e = e.next;  
           }  
284        }        }
285      return false;      return null;
286    }    }
287    
288    /**    /**
289     * Returns true if the supplied object <pre>equals()</pre> a key     * Returns true if the supplied object <code>equals()</code> a key
290     * in this HashMap.     * in this HashMap.
291     *     *
292     * @param key the key to search for in this HashMap     * @param key the key to search for in this HashMap
# Line 282  public class HashMap extends AbstractMap Line 299  public class HashMap extends AbstractMap
299      HashEntry e = buckets[idx];      HashEntry e = buckets[idx];
300      while (e != null)      while (e != null)
301        {        {
302          if (key == null ? e.key == null : key.equals(e.key))          if (equals(key, e.key))
303            return true;            return true;
304          e = e.next;          e = e.next;
305        }        }
# Line 290  public class HashMap extends AbstractMap Line 307  public class HashMap extends AbstractMap
307    }    }
308    
309    /**    /**
    * Return the value in this HashMap associated with the supplied key,  
    * or <pre>null</pre> if the key maps to nothing.  NOTE: Since the value  
    * could also be null, you must use containsKey to see if this key  
    * actually maps to something.  
    *  
    * @param key the key for which to fetch an associated value  
    * @return what the key maps to, if present  
    * @see #put(Object, Object)  
    * @see #containsKey(Object)  
    */  
   public Object get(Object key)  
   {  
     int idx = hash(key);  
     HashEntry e = buckets[idx];  
     while (e != null)  
       {  
         if (key == null ? e.key == null : key.equals(e.key))  
           return e.value;  
         e = e.next;  
       }  
     return null;  
   }  
   
   /**  
310     * Puts the supplied value into the Map, mapped by the supplied key.     * Puts the supplied value into the Map, mapped by the supplied key.
311     * The value may be retrieved by any object which <code>equals()</code>     * The value may be retrieved by any object which <code>equals()</code>
312     * this key. NOTE: Since the prior value could also be null, you must     * this key. NOTE: Since the prior value could also be null, you must
# Line 328  public class HashMap extends AbstractMap Line 321  public class HashMap extends AbstractMap
321     */     */
322    public Object put(Object key, Object value)    public Object put(Object key, Object value)
323    {    {
     modCount++;  
324      int idx = hash(key);      int idx = hash(key);
325      HashEntry e = buckets[idx];      HashEntry e = buckets[idx];
326    
327      while (e != null)      while (e != null)
328        {        {
329          if (key == null ? e.key == null : key.equals(e.key))          if (equals(key, e.key))
330            // Must use this method for necessary bookkeeping in LinkedHashMap.            // Must use this method for necessary bookkeeping in LinkedHashMap.
331            return e.setValue(value);            return e.setValue(value);
332          else          else
# Line 342  public class HashMap extends AbstractMap Line 334  public class HashMap extends AbstractMap
334        }        }
335    
336      // At this point, we know we need to add a new entry.      // At this point, we know we need to add a new entry.
337        modCount++;
338      if (++size > threshold)      if (++size > threshold)
339        {        {
340          rehash();          rehash();
# Line 355  public class HashMap extends AbstractMap Line 348  public class HashMap extends AbstractMap
348    }    }
349    
350    /**    /**
351     * Helper method for put, that creates and adds a new Entry.  This is     * Copies all elements of the given map into this hashtable.  If this table
352     * overridden in LinkedHashMap for bookkeeping purposes.     * already has a mapping for a key, the new mapping replaces the current
353       * one.
354     *     *
355     * @param key the key of the new Entry     * @param m the map to be hashed into this
    * @param value the value  
    * @param idx the index in buckets where the new Entry belongs  
    * @param callRemove Whether to call the removeEldestEntry method.  
    * @see #put(Object, Object)  
356     */     */
357    void addEntry(Object key, Object value, int idx, boolean callRemove)    public void putAll(Map m)
358    {    {
359      HashEntry e = new HashEntry(key, value);      Iterator itr = m.entrySet().iterator();
360    
361      e.next = buckets[idx];      for (int msize = m.size(); msize > 0; msize--)
362      buckets[idx] = e;        {
363            Map.Entry e = (Map.Entry) itr.next();
364            // Optimize in case the Entry is one of our own.
365            if (e instanceof BasicMapEntry)
366              {
367                BasicMapEntry entry = (BasicMapEntry) e;
368                put(entry.key, entry.value);
369              }
370            else
371              {
372                put(e.getKey(), e.getValue());
373              }
374          }
375    }    }
376      
377    /**    /**
378     * Removes from the HashMap and returns the value which is mapped by the     * Removes from the HashMap and returns the value which is mapped by the
379     * supplied key. If the key maps to nothing, then the HashMap remains     * supplied key. If the key maps to nothing, then the HashMap remains
380     * unchanged, and <pre>null</pre> is returned. NOTE: Since the value     * unchanged, and <code>null</code> is returned. NOTE: Since the value
381     * could also be null, you must use containsKey to see if you are     * could also be null, you must use containsKey to see if you are
382     * actually removing a mapping.     * actually removing a mapping.
383     *     *
# Line 384  public class HashMap extends AbstractMap Line 386  public class HashMap extends AbstractMap
386     */     */
387    public Object remove(Object key)    public Object remove(Object key)
388    {    {
     modCount++;  
389      int idx = hash(key);      int idx = hash(key);
390      HashEntry e = buckets[idx];      HashEntry e = buckets[idx];
391      HashEntry last = null;      HashEntry last = null;
392    
393      while (e != null)      while (e != null)
394        {        {
395          if (key == null ? e.key == null : key.equals(e.key))          if (equals(key, e.key))
396            {            {
397                modCount++;
398              if (last == null)              if (last == null)
399                buckets[idx] = e.next;                buckets[idx] = e.next;
400              else              else
# Line 408  public class HashMap extends AbstractMap Line 410  public class HashMap extends AbstractMap
410    }    }
411    
412    /**    /**
413     * Copies all elements of the given map into this hashtable.  If this table     * Clears the Map so it has no keys. This is O(1).
    * already has a mapping for a key, the new mapping replaces the current  
    * one.  
    *  
    * @param m the map to be hashed into this  
414     */     */
415    public void putAll(Map m)    public void clear()
416    {    {
417      Iterator itr = m.entrySet().iterator();      if (size != 0)
   
     for (int msize = m.size(); msize > 0; msize--)  
418        {        {
419          Map.Entry e = (Map.Entry) itr.next();          modCount++;
420          // Optimize in case the Entry is one of our own.          Arrays.fill(buckets, null);
421          if (e instanceof BasicMapEntry)          size = 0;
           {  
             BasicMapEntry entry = (BasicMapEntry) e;  
             put(entry.key, entry.value);  
           }  
         else  
           {  
             put(e.getKey(), e.getValue());  
           }  
422        }        }
423    }    }
424      
425    /**    /**
426     * Clears the Map so it has no keys. This is O(1).     * Returns true if this HashMap contains a value <code>o</code>, such that
427       * <code>o.equals(value)</code>.
428       *
429       * @param value the value to search for in this HashMap
430       * @return true if at least one key maps to the value
431       * @see containsKey(Object)
432     */     */
433    public void clear()    public boolean containsValue(Object value)
434    {    {
435      modCount++;      for (int i = buckets.length - 1; i >= 0; i--)
436      Arrays.fill(buckets, null);        {
437      size = 0;          HashEntry e = buckets[i];
438            while (e != null)
439              {
440                if (equals(value, e.value))
441                  return true;
442                e = e.next;
443              }
444          }
445        return false;
446    }    }
447    
448    /**    /**
# Line 463  public class HashMap extends AbstractMap Line 464  public class HashMap extends AbstractMap
464        }        }
465      copy.buckets = new HashEntry[buckets.length];      copy.buckets = new HashEntry[buckets.length];
466      copy.putAllInternal(this);      copy.putAllInternal(this);
467        copy.entries = null;
468      return copy;      return copy;
469    }    }
470    
# Line 477  public class HashMap extends AbstractMap Line 479  public class HashMap extends AbstractMap
479     */     */
480    public Set keySet()    public Set keySet()
481    {    {
482      // Create an AbstractSet with custom implementations of those methods that      if (keys == null)
483      // can be overridden easily and efficiently.        // Create an AbstractSet with custom implementations of those methods
484      return new AbstractSet()        // that can be overridden easily and efficiently.
485      {        keys = new AbstractSet()
486        public int size()        {
487        {          public int size()
488          return size;          {
489        }            return size;
490            }
491        public Iterator iterator()  
492        {          public Iterator iterator()
493          // Cannot create the iterator directly, because of LinkedHashMap.          {
494          return HashMap.this.iterator(KEYS);            // Cannot create the iterator directly, because of LinkedHashMap.
495        }            return HashMap.this.iterator(KEYS);
496            }
497        public void clear()  
498        {          public void clear()
499          HashMap.this.clear();          {
500        }            HashMap.this.clear();
501            }
502        public boolean contains(Object o)  
503        {          public boolean contains(Object o)
504          return HashMap.this.containsKey(o);          {
505        }            return containsKey(o);
506            }
507        public boolean remove(Object o)  
508        {          public boolean remove(Object o)
509          // Test against the size of the HashMap to determine if anything          {
510          // really got removed. This is neccessary because the return value of            // Test against the size of the HashMap to determine if anything
511          // HashMap.remove() is ambiguous in the null case.            // really got removed. This is neccessary because the return value
512          int oldsize = size;            // of HashMap.remove() is ambiguous in the null case.
513          HashMap.this.remove(o);            int oldsize = size;
514          return (oldsize != size);            HashMap.this.remove(o);
515        }            return oldsize != size;
516      };          }
517          };
518        return keys;
519    }    }
520    
521    /**    /**
# Line 526  public class HashMap extends AbstractMap Line 530  public class HashMap extends AbstractMap
530     */     */
531    public Collection values()    public Collection values()
532    {    {
533      // We don't bother overriding many of the optional methods, as doing so      if (values == null)
534      // wouldn't provide any significant performance advantage.        // We don't bother overriding many of the optional methods, as doing so
535      return new AbstractCollection()        // wouldn't provide any significant performance advantage.
536      {        values = new AbstractCollection()
537        public int size()        {
538        {          public int size()
539          return size;          {
540        }            return size;
541            }
542        public Iterator iterator()  
543        {          public Iterator iterator()
544          // Cannot create the iterator directly, because of LinkedHashMap.          {
545          return HashMap.this.iterator(VALUES);            // Cannot create the iterator directly, because of LinkedHashMap.
546        }            return HashMap.this.iterator(VALUES);
547            }
548        public void clear()  
549        {          public void clear()
550          HashMap.this.clear();          {
551        }            HashMap.this.clear();
552      };          }
553          };
554        return values;
555    }    }
556    
557    /**    /**
558     * Returns a "set view" of this HashMap's entries. The set is backed by     * Returns a "set view" of this HashMap's entries. The set is backed by
559     * the HashMap, so changes in one show up in the other.  The set supports     * the HashMap, so changes in one show up in the other.  The set supports
560     * element removal, but not element addition.     * element removal, but not element addition.<p>
    * <p>  
561     *     *
562     * Note that the iterators for all three views, from keySet(), entrySet(),     * Note that the iterators for all three views, from keySet(), entrySet(),
563     * and values(), traverse the HashMap in the same sequence.     * and values(), traverse the HashMap in the same sequence.
# Line 564  public class HashMap extends AbstractMap Line 569  public class HashMap extends AbstractMap
569     */     */
570    public Set entrySet()    public Set entrySet()
571    {    {
572      // Create an AbstractSet with custom implementations of those methods that      if (entries == null)
573      // can be overridden easily and efficiently.        // Create an AbstractSet with custom implementations of those methods
574      return new AbstractSet()        // that can be overridden easily and efficiently.
575      {        entries = new AbstractSet()
576        public int size()        {
577        {          public int size()
578          return size;          {
579        }            return size;
580            }
581        public Iterator iterator()  
582        {          public Iterator iterator()
583          // Cannot create the iterator directly, because of LinkedHashMap.          {
584          return HashMap.this.iterator(ENTRIES);            // Cannot create the iterator directly, because of LinkedHashMap.
585        }            return HashMap.this.iterator(ENTRIES);
586            }
587        public void clear()  
588        {          public void clear()
589          HashMap.this.clear();          {
590        }            HashMap.this.clear();
591            }
592        public boolean contains(Object o)  
593        {          public boolean contains(Object o)
594          return getEntry(o) != null;          {
595        }            return getEntry(o) != null;
596            }
597        public boolean remove(Object o)  
598        {          public boolean remove(Object o)
599          HashEntry e = getEntry(o);          {
600          if (e != null)            HashEntry e = getEntry(o);
601            {            if (e != null)
602              HashMap.this.remove(e.key);              {
603              return true;                HashMap.this.remove(e.key);
604            }                return true;
605          return false;              }
606        }            return false;
607      };          }
608          };
609        return entries;
610    }    }
611    
612    /** Helper method that returns an index in the buckets array for `key;    /**
613     * based on its hashCode().     * Helper method for put, that creates and adds a new Entry.  This is
614       * overridden in LinkedHashMap for bookkeeping purposes.
615     *     *
616     * @param key the key     * @param key the key of the new Entry
617     * @return the bucket number     * @param value the value
618       * @param idx the index in buckets where the new Entry belongs
619       * @param callRemove whether to call the removeEldestEntry method
620       * @see #put(Object, Object)
621     */     */
622    int hash(Object key)    void addEntry(Object key, Object value, int idx, boolean callRemove)
623    {    {
624      return (key == null) ? 0 : Math.abs(key.hashCode() % buckets.length);      HashEntry e = new HashEntry(key, value);
625    
626        e.next = buckets[idx];
627        buckets[idx] = e;
628    }    }
629    
630    /**    /**
# Line 638  public class HashMap extends AbstractMap Line 652  public class HashMap extends AbstractMap
652    }    }
653    
654    /**    /**
655       * Helper method that returns an index in the buckets array for `key'
656       * based on its hashCode().  Package visible for use by subclasses.
657       *
658       * @param key the key
659       * @return the bucket number
660       */
661      final int hash(Object key)
662      {
663        return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
664      }
665    
666      /**
667       * Generates a parameterized iterator.  Must be overrideable, since
668       * LinkedHashMap iterates in a different order.
669       *
670       * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
671       * @return the appropriate iterator
672       */
673      Iterator iterator(int type)
674      {
675        return new HashIterator(type);
676      }
677    
678      /**
679       * A simplified, more efficient internal implementation of putAll(). The
680       * Map constructor and clone() should not call putAll or put, in order to
681       * be compatible with the JDK implementation with respect to subclasses.
682       *
683       * @param m the map to initialize this from
684       */
685      void putAllInternal(Map m)
686      {
687        Iterator itr = m.entrySet().iterator();
688    
689        for (int msize = m.size(); msize > 0; msize--)
690          {
691            Map.Entry e = (Map.Entry) itr.next();
692            Object key = e.getKey();
693            int idx = hash(key);
694            addEntry(key, e.getValue(), idx, false);
695          }
696      }
697    
698      /**
699     * Increases the size of the HashMap and rehashes all keys to new array     * Increases the size of the HashMap and rehashes all keys to new array
700     * indices; this is called when the addition of a new value would cause     * indices; this is called when the addition of a new value would cause
701     * size() > threshold. Note that the existing Entry objects are reused in     * size() > threshold. Note that the existing Entry objects are reused in
# Line 682  public class HashMap extends AbstractMap Line 740  public class HashMap extends AbstractMap
740    }    }
741    
742    /**    /**
    * Generates a parameterized iterator.  Must be overrideable, since  
    * LinkedHashMap iterates in a different order.  
    * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}  
    * @return the appropriate iterator  
    */  
   Iterator iterator(int type)  
   {  
     return new HashIterator(type);  
   }  
   
   /**  
    * A simplified, more efficient internal implementation of putAll(). The  
    * Map constructor and clone() should not call putAll or put, in order to  
    * be compatible with the JDK implementation with respect to subclasses.  
    */  
   void putAllInternal(Map m)  
   {  
     Iterator itr = m.entrySet().iterator();  
   
     for (int msize = m.size(); msize > 0; msize--)  
       {  
         Map.Entry e = (Map.Entry) itr.next();  
         Object key = e.getKey();  
         int idx = hash(key);  
         addEntry(key, e.getValue(), idx, false);  
       }  
   }  
   
   /**  
743     * Serializes this object to the given stream.     * Serializes this object to the given stream.
744     *     *
745     * @param s the stream to write to     * @param s the stream to write to
# Line 757  public class HashMap extends AbstractMap Line 786  public class HashMap extends AbstractMap
786      // Read and use capacity.      // Read and use capacity.
787      buckets = new HashEntry[s.readInt()];      buckets = new HashEntry[s.readInt()];
788      int len = s.readInt();      int len = s.readInt();
     // Already happens automatically.  
     // size = 0;  
     // modCount = 0;  
789    
790      // Read and use key/value pairs.      // Read and use key/value pairs.
791      for ( ; len > 0; len--)      for ( ; len > 0; len--)
# Line 773  public class HashMap extends AbstractMap Line 799  public class HashMap extends AbstractMap
799     *     *
800     * @author Jon Zeppieri     * @author Jon Zeppieri
801     */     */
802    class HashIterator implements Iterator    private final class HashIterator implements Iterator
803    {    {
804      /**      /**
805       * The type of this Iterator: {@link #KEYS}, {@link #VALUES},       * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
806       * or {@link #ENTRIES}.       * or {@link #ENTRIES}.
807       */       */
808      final int type;      private final int type;
809      /**      /**
810       * The number of modifications to the backing HashMap that we know about.       * The number of modifications to the backing HashMap that we know about.
811       */       */
812      int knownMod = modCount;      private int knownMod = modCount;
813      /** The number of elements remaining to be returned by next(). */      /** The number of elements remaining to be returned by next(). */
814      int count = size;      private int count = size;
815      /** Current index in the physical hash table. */      /** Current index in the physical hash table. */
816      int idx = buckets.length;      private int idx = buckets.length;
817      /** The last Entry returned by a next() call. */      /** The last Entry returned by a next() call. */
818      HashEntry last;      private HashEntry last;
819      /**      /**
820       * The next entry that should be returned by next(). It is set to something       * The next entry that should be returned by next(). It is set to something
821       * if we're iterating through a bucket that contains multiple linked       * if we're iterating through a bucket that contains multiple linked
822       * entries. It is null if next() needs to find a new bucket.       * entries. It is null if next() needs to find a new bucket.
823       */       */
824      HashEntry next;      private HashEntry next;
825    
826      /**      /**
827       * Construct a new HashIterator with the supplied type.       * Construct a new HashIterator with the supplied type.
# Line 840  public class HashMap extends AbstractMap Line 866  public class HashMap extends AbstractMap
866        last = e;        last = e;
867        if (type == VALUES)        if (type == VALUES)
868          return e.value;          return e.value;
869        else if (type == KEYS)        if (type == KEYS)
870          return e.key;          return e.key;
871        return e;        return e;
872      }      }
873    
874      /**      /**
875       * Removes from the backing HashMap the last element which was fetched       * Removes from the backing HashMap the last element which was fetched
876       * with the <pre>next()</pre> method.       * with the <code>next()</code> method.
877       * @throws ConcurrentModificationException if the HashMap was modified       * @throws ConcurrentModificationException if the HashMap was modified
878       * @throws IllegalStateException if called when there is no last element       * @throws IllegalStateException if called when there is no last element
879       */       */
# Line 859  public class HashMap extends AbstractMap Line 885  public class HashMap extends AbstractMap
885          throw new IllegalStateException();          throw new IllegalStateException();
886    
887        HashMap.this.remove(last.key);        HashMap.this.remove(last.key);
       knownMod++;  
888        last = null;        last = null;
889          knownMod++;
890      }      }
891    }    }
892  }  }

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.17

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26