FileDocCategorySizeDatePackage
HashMap.javaAPI DocAndroid 1.5 API24580Wed May 06 22:41:04 BST 2009java.util

HashMap

public class HashMap extends AbstractMap implements Serializable, Cloneable, Map
HashMap is an implementation of Map. All optional operations (adding and removing) are supported. Keys and values can be any objects.
since
Android 1.0

Fields Summary
private static final long
serialVersionUID
transient int
elementCount
transient Entry[]
elementData
final float
loadFactor
int
threshold
transient int
modCount
private static final int
DEFAULT_SIZE
Constructors Summary
public HashMap()
Constructs a new empty {@code HashMap} instance.

since
Android 1.0

        this(DEFAULT_SIZE);
    
public HashMap(int capacity)
Constructs a new {@code HashMap} instance with the specified capacity.

param
capacity the initial capacity of this hash map.
throws
IllegalArgumentException when the capacity is less than zero.
since
Android 1.0

        if (capacity >= 0) {
            elementCount = 0;
            elementData = newElementArray(capacity == 0 ? 1 : capacity);
            loadFactor = 0.75f; // Default load factor of 0.75
            computeMaxSize();
        } else {
            throw new IllegalArgumentException();
        }
    
public HashMap(int capacity, float loadFactor)
Constructs a new {@code HashMap} instance with the specified capacity and load factor.

param
capacity the initial capacity of this hash map.
param
loadFactor the initial load factor.
throws
IllegalArgumentException when the capacity is less than zero or the load factor is less or equal to zero.
since
Android 1.0

        if (capacity >= 0 && loadFactor > 0) {
            elementCount = 0;
            elementData = newElementArray(capacity == 0 ? 1 : capacity);
            this.loadFactor = loadFactor;
            computeMaxSize();
        } else {
            throw new IllegalArgumentException();
        }
    
public HashMap(Map map)
Constructs a new {@code HashMap} instance containing the mappings from the specified map.

param
map the mappings to add.
since
Android 1.0

        this(map.size() < 6 ? 11 : map.size() * 2);
        putAllImpl(map);
    
Methods Summary
public voidclear()
Removes all mappings from this hash map, leaving it empty.

see
#isEmpty
see
#size
since
Android 1.0

        internalClear();
    
public java.lang.Objectclone()
Returns a shallow copy of this map.

return
a shallow copy of this map.
since
Android 1.0

        try {
            // BEGIN android-changed
            // copied from newer version of harmony
            HashMap<K, V> map = (HashMap<K, V>) super.clone();
            map.elementData = newElementArray(elementData.length);
            map.internalClear();
            Entry<K, V> entry;
            for (int i = 0; i < elementData.length; i++) {
                if ((entry = elementData[i]) != null){
                    map.putImpl(entry.getKey(), entry.getValue());
                    while (entry.next != null){
                        entry = entry.next;
                        map.putImpl(entry.getKey(), entry.getValue());
                    }
                }
            // END android-changed
            }
            return map;
        } catch (CloneNotSupportedException e) {
            return null;
        }
    
private voidcomputeMaxSize()

        threshold = (int) (elementData.length * loadFactor);
    
public booleancontainsKey(java.lang.Object key)
Returns whether this map contains the specified key.

param
key the key to search for.
return
{@code true} if this map contains the specified key, {@code false} otherwise.
since
Android 1.0

        Entry<K, V> m;
        if (key == null) {
            m = findNullKeyEntry();
        } else {
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % elementData.length;
            m = findNonNullKeyEntry(key, index, hash);
        }
        return m != null;
    
public booleancontainsValue(java.lang.Object value)
Returns whether this map contains the specified value.

param
value the value to search for.
return
{@code true} if this map contains the specified value, {@code false} otherwise.
since
Android 1.0

        if (value != null) {
            for (int i = elementData.length; --i >= 0;) {
                Entry<K, V> entry = elementData[i];
                while (entry != null) {
                    if (value.equals(entry.value)) {
                        return true;
                    }
                    entry = entry.next;
                }
            }
        } else {
            for (int i = elementData.length; --i >= 0;) {
                Entry<K, V> entry = elementData[i];
                while (entry != null) {
                    if (entry.value == null) {
                        return true;
                    }
                    entry = entry.next;
                }
            }
        }
        return false;
    
java.util.HashMap$EntrycreateEntry(K key, int index, V value)

        Entry<K, V> entry = new Entry<K, V>(key, value);
        entry.next = elementData[index];
        elementData[index] = entry;
        return entry;
    
java.util.HashMap$EntrycreateHashedEntry(K key, int index, int hash)

        Entry<K,V> entry = new Entry<K,V>(key,hash);
        entry.next = elementData[index];
        elementData[index] = entry;
        return entry;
    
public java.util.SetentrySet()
Returns a set containing all of the mappings in this map. Each mapping is an instance of {@link Map.Entry}. As the set is backed by this map, changes in one will be reflected in the other.

return
a set of the mappings.
since
Android 1.0

        return new HashMapEntrySet<K, V>(this);
    
final java.util.HashMap$EntryfindNonNullKeyEntry(java.lang.Object key, int index, int keyHash)

        Entry<K,V> m = elementData[index];
        // BEGIN android-changed
        // The VM can optimize String.equals but not Object.equals
        if (key instanceof String) {
            String keyString = (String) key;
            while (m != null) {
                if (m.origKeyHash == keyHash) {
                    if (keyString.equals(m.key)) {
                        return m;
                    }
                }
                m = m.next;
            }
        } else {
            while (m != null) {
                if (m.origKeyHash == keyHash) {
                    if (key.equals(m.key)) {
                        return m;
                    }
                }
                m = m.next;
            }
        }
        return null;
        // END android-changed
    
final java.util.HashMap$EntryfindNullKeyEntry()

        Entry<K,V> m = elementData[0];
        while (m != null && m.key != null)
            m = m.next;
        return m;
    
public Vget(java.lang.Object key)
Returns the value of the mapping with the specified key.

param
key the key.
return
the value of the mapping with the specified key, or {@code null} if no mapping for the specified key is found.
since
Android 1.0

        Entry<K, V> m;
        if (key == null) {
            m = findNullKeyEntry();
        } else {
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % elementData.length;
            m = findNonNullKeyEntry(key, index, hash);
        }
        if (m != null) {
            return m.value;
        }
        return null;
    
voidinternalClear()

        if (elementCount > 0) {
            elementCount = 0;
            Arrays.fill(elementData, null);
            modCount++;
        }
    
public booleanisEmpty()
Returns whether this map is empty.

return
{@code true} if this map has no elements, {@code false} otherwise.
see
#size()
since
Android 1.0

        return elementCount == 0;
    
public java.util.SetkeySet()
Returns a set of the keys contained in this map. The set is backed by this map so changes to one are reflected by the other. The set does not support adding.

return
a set of the keys.
since
Android 1.0

        if (keySet == null) {
            keySet = new AbstractSet<K>() {
                @Override
                public boolean contains(Object object) {
                    return containsKey(object);
                }

                @Override
                public int size() {
                    return HashMap.this.size();
                }

                @Override
                public void clear() {
                    HashMap.this.clear();
                }

                @Override
                public boolean remove(Object key) {
                    Entry<K, V> entry = HashMap.this.removeEntry(key);
                    return entry != null;
                }

                @Override
                public Iterator<K> iterator() {
                    return new HashMapIterator<K, K, V>(
                            new MapEntry.Type<K, K, V>() {
                                public K get(MapEntry<K, V> entry) {
                                    return entry.key;
                                }
                            }, HashMap.this);
                }
            };
        }
        return keySet;
    
java.util.HashMap$Entry[]newElementArray(int s)

        return new Entry[s];
    
public Vput(K key, V value)
Maps the specified key to the specified value.

param
key the key.
param
value the value.
return
the value of any previous mapping with the specified key or {@code null} if there was no such mapping.
since
Android 1.0

        return putImpl(key, value);
    
public voidputAll(java.util.Map map)
Copies all the mappings in the specified map to this map. These mappings will replace all mappings that this map had for any of the keys currently in the given map.

param
map the map to copy mappings from.
since
Android 1.0

        if (!map.isEmpty()) {
            putAllImpl(map);
        }
    
private voidputAllImpl(java.util.Map map)

        int capacity = elementCount + map.size();
        if (capacity > threshold) {
            rehash(capacity);
        }
        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
            putImpl(entry.getKey(), entry.getValue());
        }
    
private VputImpl(K key, V value)

        Entry<K,V> entry;
        if(key == null) {
            entry = findNullKeyEntry();
            if (entry == null) {
                modCount++;
                if (++elementCount > threshold) {
                    rehash();
                }
                entry = createHashedEntry(key, 0, 0);
            }
        } else {
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % elementData.length;
            entry = findNonNullKeyEntry(key, index, hash);
            if (entry == null) {
                modCount++;
                if (++elementCount > threshold) {
                    rehash();
                    index = (hash & 0x7FFFFFFF) % elementData.length;
                }
                entry = createHashedEntry(key, index, hash);
            }
        }

        V result = entry.value;
        entry.value = value;
        return result;
    
private voidreadObject(java.io.ObjectInputStream stream)

        stream.defaultReadObject();
        int length = stream.readInt();
        elementData = newElementArray(length);
        elementCount = stream.readInt();
        for (int i = elementCount; --i >= 0;) {
            K key = (K) stream.readObject();
            int index = (null == key) ? 0 : (key.hashCode() & 0x7FFFFFFF)
                    % length;
            createEntry(key, index, (V) stream.readObject());
        }
    
voidrehash(int capacity)

        int length = (capacity == 0 ? 1 : capacity << 1);

        Entry<K, V>[] newData = newElementArray(length);
        for (int i = 0; i < elementData.length; i++) {
            Entry<K, V> entry = elementData[i];
            while (entry != null) {
                int index = (entry.origKeyHash & 0x7FFFFFFF) % length;
                Entry<K, V> next = entry.next;
                entry.next = newData[index];
                newData[index] = entry;
                entry = next;
            }
        }
        elementData = newData;
        computeMaxSize();
    
voidrehash()

        rehash(elementData.length);
    
public Vremove(java.lang.Object key)
Removes the mapping with the specified key from this map.

param
key the key of the mapping to remove.
return
the value of the removed mapping or {@code null} if no mapping for the specified key was found.
since
Android 1.0

        Entry<K, V> entry = removeEntry(key);
        if (entry != null) {
            return entry.value;
        }
        return null;
    
java.util.HashMap$EntryremoveEntry(java.lang.Object key)

        int index = 0;
        Entry<K, V> entry;
        Entry<K, V> last = null;
        if (key != null) {
            int hash = key.hashCode();
            index = (hash & 0x7FFFFFFF) % elementData.length;
            entry = elementData[index];
            while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) {
                last = entry;
                entry = entry.next;
            }
        } else {
            entry = elementData[0];
            while (entry != null && entry.key != null) {
                last = entry;
                entry = entry.next;
            }
        }
        if (entry == null) {
            return null;
        }
        if (last == null) {
            elementData[index] = entry.next;
        } else {
            last.next = entry.next;
        }
        modCount++;
        elementCount--;
        return entry;
    
public intsize()
Returns the number of elements in this map.

return
the number of elements in this map.
since
Android 1.0

        return elementCount;
    
public java.util.Collectionvalues()
Returns a collection of the values contained in this map. The collection is backed by this map so changes to one are reflected by the other. The collection supports remove, removeAll, retainAll and clear operations, and it does not support add or addAll operations.

This method returns a collection which is the subclass of AbstractCollection. The iterator method of this subclass returns a "wrapper object" over the iterator of map's entrySet(). The {@code size} method wraps the map's size method and the {@code contains} method wraps the map's containsValue method.

The collection is created when this method is called for the first time and returned in response to all subsequent calls. This method may return different collections when multiple concurrent calls occur, since no synchronization is performed.

return
a collection of the values contained in this map.
since
Android 1.0

        if (valuesCollection == null) {
            valuesCollection = new AbstractCollection<V>() {
                @Override
                public boolean contains(Object object) {
                    return containsValue(object);
                }

                @Override
                public int size() {
                    return HashMap.this.size();
                }

                @Override
                public void clear() {
                    HashMap.this.clear();
                }

                @Override
                public Iterator<V> iterator() {
                    return new HashMapIterator<V, K, V>(
                            new MapEntry.Type<V, K, V>() {
                                public V get(MapEntry<K, V> entry) {
                                    return entry.value;
                                }
                            }, HashMap.this);
                }
            };
        }
        return valuesCollection;
    
private voidwriteObject(java.io.ObjectOutputStream stream)

        stream.defaultWriteObject();
        stream.writeInt(elementData.length);
        stream.writeInt(elementCount);
        Iterator<?> iterator = entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<?, ?> entry = (Entry<?, ?>) iterator.next();
            stream.writeObject(entry.key);
            stream.writeObject(entry.value);
            entry = entry.next;
        }