LinkedHashMap.java revision 0
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This code is free software; you can redistribute it and/or modify it
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * under the terms of the GNU General Public License version 2 only, as
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * published by the Free Software Foundation. Sun designates this
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * particular file as subject to the "Classpath" exception as provided
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * by Sun in the LICENSE file that accompanied this code.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This code is distributed in the hope that it will be useful, but WITHOUT
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * version 2 for more details (a copy is included in the LICENSE file that
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * accompanied this code).
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * You should have received a copy of the GNU General Public License version
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * 2 along with this work; if not, write to the Free Software Foundation,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * CA 95054 USA or visit www.sun.com if you need additional information or
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * have any questions.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Hash table based implementation of the Map interface. This implementation
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * provides all of the optional Map operations, and permits null values and
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the null key. (HashMap is roughly equivalent to Hashtable, except that it
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * is unsynchronized and permits nulls.) In addition, elements in the map are
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * ordered and doubly linked together.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * This implementation provides constant-time performance for the basic
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * operations (get and put), assuming the the hash function disperses the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * elements properly among the buckets. Iteration over Collection views
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * requires time proportional to its size (the number of key-value mappings)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * and returns elements in the order they are linked. In a HashMap the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * iteration would require time proportional to the capacity of the map
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * plus the map size.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * An instance of LinkedHashMap has two parameters that affect its efficiency:
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * its <i>capacity</i> and its <i>load factor</i>. The load factor should be
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * between 0.0 and 1.0. When the number of mappings in the LinkedHashMap exceeds
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the product of the load factor and the current capacity, the capacity is
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * increased by calling the rehash method which requires time proportional
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * to the number of key-value mappings in the map. Larger load factors
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * use memory more efficiently, at the expense of larger expected time per
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * If many mappings are to be stored in a LinkedHashMap, creating it with a
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * sufficiently large capacity will allow the mappings to be stored more
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * efficiently than letting it perform automatic rehashing as needed to grow
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the table.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * <strong>Note that this implementation is not synchronized.</strong> If
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * multiple threads access a LinkedHashMap concurrently, and at least one of the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * threads modifies the LinkedHashMap structurally, it <em>must</em> be
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * synchronized externally. (A structural modification is any operation that
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * adds or deletes one or more mappings; merely changing the value associated
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * with a key that is already contained in the Table is not a structural
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * modification.) This is typically accomplished by synchronizing on some
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * object that naturally encapsulates the LinkedHashMap. If no such object
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * exists, the LinkedHashMap should be "wrapped" using the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Collections.synchronizedSet method. This is best done at creation time, to
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * prevent accidental unsynchronized access to the LinkedHashMap:
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Map m = Collections.synchronizedMap(new LinkedHashMap(...));
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The Iterators returned by the iterator methods of the Collections returned
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * by all of LinkedHashMap's "collection view methods" are <em>fail-fast</em>:
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * if the LinkedHashMap is structurally modified at any time after the Iterator
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * is created, in any way except through the Iterator's own remove or add
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * methods, the Iterator will throw a ConcurrentModificationException. Thus,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * in the face of concurrent modification, the Iterator fails quickly and
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * cleanly, rather than risking arbitrary, non-deterministic behavior at an
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * undetermined time in the future.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @author Josh Bloch
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @author Arthur van Hoff
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @author Zhenghua Li
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see Object#hashCode()
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see java.util.Collection
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see java.util.Map
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see java.util.TreeMap
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see java.util.Hashtable
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @see java.util.HashMap
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenkpublic class LinkedHashMap extends AbstractMap implements Map, Serializable {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The hash table data.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The head of the double linked list.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The total number of mappings in the hash table.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk private transient int count;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Rehashes the table when count exceeds this threshold.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The load factor for the LinkedHashMap.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk private float loadFactor;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * The number of times this LinkedHashMap has been structurally modified
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Structural modifications are those that change the number of mappings in
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the LinkedHashMap or otherwise modify its internal structure (e.g.,
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * rehash). This field is used to make iterators on Collection-views of
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the LinkedHashMap fail-fast. (See ConcurrentModificationException).
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Constructs a new, empty LinkedHashMap with the specified initial
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * capacity and the specified load factor.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param initialCapacity the initial capacity of the LinkedHashMap.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param loadFactor a number between 0.0 and 1.0.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @exception IllegalArgumentException if the initial capacity is less
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * than or equal to zero, or if the load factor is less than
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * or equal to zero.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk public LinkedHashMap(int initialCapacity, float loadFactor) {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk throw new IllegalArgumentException("Illegal Initial Capacity: "+
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk throw new IllegalArgumentException("Illegal Load factor: "+
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk threshold = (int)(initialCapacity * loadFactor);
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Constructs a new, empty LinkedHashMap with the specified initial capacity
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * and default load factor.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param initialCapacity the initial capacity of the LinkedHashMap.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Constructs a new, empty LinkedHashMap with a default capacity and load
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Constructs a new LinkedHashMap with the same mappings as the given
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Map. The LinkedHashMap is created with a capacity of thrice the number
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * of mappings in the given Map or 11 (whichever is greater), and a
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * default load factor.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns the number of key-value mappings in this Map.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk public int size() {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns true if this Map contains no key-value mappings.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk public boolean isEmpty() {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns true if this LinkedHashMap maps one or more keys to the specified
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param value value whose presence in this Map is to be tested.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = header.after; e != header; e = e.after)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return true;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = header.after; e != header; e = e.after)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return true;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return false;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns true if this LinkedHashMap contains a mapping for the specified
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param key key whose presence in this Map is to be tested.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = tab[index]; e != null; e = e.next)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return true;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return true;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk return false;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns the value to which this LinkedHashMap maps the specified key.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns null if the LinkedHashMap contains no mapping for this key.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * A return value of null does not <em>necessarily</em> indicate that the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * LinkedHashMap contains no mapping for the key; it's also possible that
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the LinkedHashMap explicitly maps the key to null. The containsKey
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * operation may be used to distinguish these two cases.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param key key whose associated value is to be returned.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns the entry associated with the specified key in the LinkedHashMap.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns null if the LinkedHashMap contains no mapping for this key.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = tab[index]; e != null; e = e.next)
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Rehashes the contents of the LinkedHashMap into a LinkedHashMap with a
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * larger capacity. This method is called automatically when the
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * number of keys in the LinkedHashMap exceeds this LinkedHashMap's capacity
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * and load factor.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk private void rehash() {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = header.after; e != header; e = e.after) {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk int index = (e.hash & 0x7FFFFFFF) % newCapacity;
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Remove an entry from the linked list.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Add the specified entry before the specified existing entry to
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * the linked list.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk private void listAddBefore(Entry entry, Entry existEntry) {
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * Returns the position of the mapping for the specified key
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * in the ordered map.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @param key the specified key.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk * @return index of the key mapping.
c1350cf5bc50458ba79cc93ff9e0e5fe3f1aeeb0jeff.schenk for (Entry e = header.after; e != header; e = e.after, i++)
return old;
return old;
modCount++;
rehash();
count++;
return null;
throw new IndexOutOfBoundsException();
e = e.after;
modCount++;
count--;
listRemove(e);
return oldValue;
modCount++;
count--;
listRemove(e);
return oldValue;
return null;
while (i.hasNext()) {
public void clear() {
modCount++;
return new LinkedHashMap(this);
public int size() {
return count;
return containsKey(o);
public void clear() {
return keySet;
public int size() {
return count;
return containsValue(o);
public void clear() {
return values;
modCount++;
count--;
listRemove(e);
public int size() {
return count;
public void clear() {
return entries;
if (!(o instanceof LinkedHashMap))
int hash;
return key;
return value;
return oldValue;
public int hashCode() {
private int type;
public boolean hasNext() {
throw new ConcurrentModificationException();
throw new NoSuchElementException();
public void remove() {
throw new IllegalStateException();
throw new ConcurrentModificationException();
if (e == lastReturned) {
modCount++;
count--;
listRemove(e);
throw new ConcurrentModificationException();
throws IOException
s.defaultWriteObject();
s.defaultReadObject();