HashMap实现

 *  |Map
 *  |   --ConcurrentMap
 *  |       --ConcurrentHashMap
 *  |   --SortedMap
 *  |       --NavigableMap
 *  |           --TreeMap
 *  |   --AbstractMap
 *  |       --HashMap
 *  |           --LinkedHashMap
 *  |       --WeakHashMap
 *  |       --IdentityHashMap
 *  |       --TreeMap
 *  |       --EnumMap

Map是映射接口,里面存储的是键值对。

  • SortedMap 是继承于Map的接口。SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。
  • NavigableMap是继承于SortedMap的接口。相比于SortedMap,NavigableMap有一系列的导航方法;如”获取大于/等于某对象的键值对”、“获取小于/等于某对象的键值对”等等。
  • TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是“有序的键值对”
  • HashMap 继承于AbstractMap,但没实现NavigableMap接口;因此,HashMap的内容是“键值对,但不保证次序”
  • WeakHashMap 继承于AbstractMap。它和HashMap的键类型不同,WeakHashMap的键是“弱键”。

1.Map:

public interface Map<K,V> {
    int size();
    boolean isEmpty();
    boolean containsKey(Object key);
    boolean containsValue(Object value);
    V get(Object key);
    V put(K key, V value);
    V remove(Object key);
    void putAll(Map<? extends K, ? extends V> m); 
    Set<K> keySet();//获得所有键 
    Set<Map.Entry<K, V>> entrySet();//返回此映射中包含的映射关系的Set视图 
    int hashCode(); 
    interface Entry<K,V> {
        K getKey();
        V getValue();
        V setValue(V value);
        boolean equals(Object o);
        int hashCode(); 
    }
}
  • KeySet 是一个 Map 中键(key)的集合,以 Set 的形式保存,不允许重复,因此键存储的对象需要重写 equals() 和hashCode() 方法。
  • Values 是一个 Map 中值 (value) 的集合,以 Collection 的形式保存,因此可以重复。
  • Entry是Map的内部接口,表示键值对的映射。Map通过keySet()获取Map.Entry的键值对集合,保存在Set中,通过该集合实现对键值对的操作,所以Entry也不能重复。

Map的3种遍历方式:
1.使用 keySet 遍历:

Set set = map.keySet();
for (Object key : set) {
    System.out.println(map.get(key));
}

2.使用 values 遍历:

Collection values = map.values();
Iterator iterator = values.iterator();
while (iterator.hasNext()){
    System.out.println("value " + iterator.next());
}

3.使用 Entry 遍历

Set entrySet = map.entrySet();
for (Object o : entrySet) {
    Map.Entry entry = (Map.Entry) o;
    System.out.println(entry);      //key=value
    System.out.println(entry.getKey() + " / " + entry.getValue());
}

2.AbstractMap

定义
public abstract class AbstractMap

//获取所有键值对,需要子类实现,AbstarctMap 中唯一的抽象方法
public abstract Set<Entry<K,V>> entrySet();

AbstractMap成员变量

    transient volatile Set<K>        keySet = null;
    transient volatile Collection<V> values = null;

keySet保存map中所有的键,values保存所有的值。使用transient volatile 表示不可序列化,并发环境修改变量会保证线程可见性

具体函数实现
获取:

    public V get(Object key) {//很多实现类重写了该方法;时间复杂度O(n)
        //获取保存Map.Entry集合的迭代器
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (key==null) {//查询分为null和非null
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)//存在Key为null的数据
                    return e.getValue();
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return e.getValue();
            }
        }
        return null;
    }

添加:

    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }

默认是不支持添加操作,所以如果要实现不可变的Map,只需要继承这个类重写entrySet()方法;如果要实现可变的类,需要重写put(key,value)方法
删除:

public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;//用于记录要删除的Entry<K,V>数据
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }

        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();//从Entry<K,V>获取value
            i.remove();
        }
        return oldValue;
    }

查询某Key或者某value是否存在

public boolean containsValue(Object value) {//O(n),
    Iterator<Entry<K,V>> i = entrySet().iterator();
    if (value==null) {
        while (i.hasNext()) {
            Entry<K,V> e = i.next();
            if (e.getValue()==null)
                return true;
        }
    } else {
        while (i.hasNext()) {
            Entry<K,V> e = i.next();
            if (value.equals(e.getValue()))
                return true;
        }
    }
    return false;
}
public boolean containsKey(Object key) {
    Iterator<Map.Entry<K,V>> i = entrySet().iterator();
    if (key==null) {
        while (i.hasNext()) {
            Entry<K,V> e = i.next();
            if (e.getKey()==null)
                return true;
        }
    } else {
        while (i.hasNext()) {
            Entry<K,V> e = i.next();
            if (key.equals(e.getKey()))
                return true;
        }
    }
    return false;
}

查询size

    public int size() {
        return entrySet().size();//查set<Entry<K,V>>的size
    }
    public boolean isEmpty() {
        return size() == 0;
    }

equals()和hashcode()

    public boolean equals(Object o) {//判断指定对象是否和当前map一致
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<K,V> m = (Map<K,V>) o;
        if (m.size() != size())
            return false;

        try {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                if (value == null) {//根据Entry<K,V>的value是否为null划分两种情况
                    if (!(m.get(key)==null && m.containsKey(key)))
                        return false;
                } else {
                    if (!value.equals(m.get(key)))
                        return false;
                }
            }
        } catch (ClassCastException unused) {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }

        return true;
    }
    public int hashCode() {//整个Map的hashCode,求和
        int h = 0;
        Iterator<Entry<K,V>> i = entrySet().iterator();
        while (i.hasNext())
            h += i.next().hashCode();
        return h;
    }

获得所有键

    public Set<K> keySet() {
        if (keySet == null) {//如果keySet为空,则创建一个空的AbstractSet
            keySet = new AbstractSet<K>() {
                public Iterator<K> iterator() {
                    return new Iterator<K>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();//Set<Entry<K,V>>.iterator()

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public K next() {
                            return i.next().getKey();
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object k) {
                    return AbstractMap.this.containsKey(k);
                }
            };
        }
        return keySet;
    }

获得所有值

    public Collection<V> values() {
        if (values == null) {
            values = new AbstractCollection<V>() {
                public Iterator<V> iterator() {
                    return new Iterator<V>() {
                        private Iterator<Entry<K,V>> i = entrySet().iterator();

                        public boolean hasNext() {
                            return i.hasNext();
                        }

                        public V next() {
                            return i.next().getValue();
                        }

                        public void remove() {
                            i.remove();
                        }
                    };
                }

                public int size() {
                    return AbstractMap.this.size();
                }

                public boolean isEmpty() {
                    return AbstractMap.this.isEmpty();
                }

                public void clear() {
                    AbstractMap.this.clear();
                }

                public boolean contains(Object v) {
                    return AbstractMap.this.containsValue(v);
                }
            };
        }
        return values;
    }

Map接口中有个Map.Entry,AbstractMap中有两个Entry,分别是

public static class SimpleEntry<K,V> implements Entry<K,V>, java.io.Serializable             //可变的键值对   
private final K key;  private V value;
public static class SimpleImmutableEntry<K,V> implements Entry<K,V>, java.io.Serializable      //不可变的键值对  
private final K key;  private final V value;

这两个内部类程序另一个区别是:SimpleImmutableEntry的setValue方法回抛UnsupportedOperationException,而另一个可以赋值。

public static class SimpleImmutableEntry<K,V>
    implements Entry<K,V>, java.io.Serializable
{
    private static final long serialVersionUID = 7138329143949025153L;

    private final K key;
    private final V value;

    public SimpleImmutableEntry(K key, V value) {
        this.key   = key;
        this.value = value;
    }

    public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
        this.key   = entry.getKey();
        this.value = entry.getValue();
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }

    public V setValue(V value) {
        throw new UnsupportedOperationException();
    }

    public boolean equals(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry e = (Map.Entry)o;
        return eq(key, e.getKey()) && eq(value, e.getValue());//eq()是AbstractMap里的方法
    }

    public int hashCode() {
        return (key   == null ? 0 :   key.hashCode()) ^
               (value == null ? 0 : value.hashCode());
    }

    public String toString() {
        return key + "=" + value;
    }

}

AbstractMap里的eq()

    private static boolean eq(Object o1, Object o2) {
        return o1 == null ? o2 == null : o1.equals(o2);
    }

3.HashMap:
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。(拉链式)
这里写图片描述

public class HashMap<K,V>  extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

HashMap实现Map接口,继承AbstractMap

HashMap数据结构只需要经过哈希运算,能得到目标元素在哈希表中的位置,然后通过比较相同位置元素,就能得到数据,所以该结构查找效率高。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。
容量是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
加载因子太大会导致冲突的可能性大,查找效率变低。太小了频繁扩容,重新哈希,性能降低。
当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。
那么HashMap什么时候进行扩容呢?
当HashMap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  //默认初始容量 16;必须是2^n
static final int MAXIMUM_CAPACITY = 1 << 30;    //最大容量2^30
static final float DEFAULT_LOAD_FACTOR = 0.75f;  //默认加载因子0.75
static final Entry<?,?>[] EMPTY_TABLE = {};//当数组还没有进行扩容操作时候共享的一个空表对象
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;  //链表数组
transient int size; //键值对数量
int threshold;  //阈值,下次需要扩充时的值,用于判断是否需要扩容  = 容量*加载因子
final float loadFactor;     //哈希表的加载因子
transient int modCount;     //hashMap每次修改,会+1,为了保证快速失败机制(fail-fast)
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
transient int hashSeed = 0;//用于计算Key的hash值,它与key的hashCode进行按位异或运算。这个hashSeed是一个与实例相关的随机值,主要用于解决hash冲突

构造方法:

    //设置容量和加载因子     
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +loadFactor);
        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();
    }
    //指定容量,默认加载因子
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    //使用默认初始容量和加载因子创建哈希表
    public HashMap() {
        this(DEFAULT_INITIAL_CAPACITY,DEFAULT_LOAD_FACTOR);
    }
    //创建m的哈希表
    public HashMap(Map<? extends K, ? extends V> m) {
        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
        inflateTable(threshold);//扩容
        // 将m中的全部元素逐个添加到HashMap中
        putAllForCreate(m);
    }
    private void inflateTable(int toSize) {
        int capacity = roundUpToPowerOf2(toSize);//判断值是否大于最大值,大于则设置该值为最大值;否则计算出大于toSize最临近的2的N此方的值 
    //这里展示了 阈值 = 数组大小 * 加载因子
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
        table = new Entry[capacity];//
        initHashSeedAsNeeded(capacity);
    }
    //初始化hashSeed
    final boolean initHashSeedAsNeeded(int capacity) {
        boolean currentAltHashing = hashSeed != 0;
        boolean useAltHashing = sun.misc.VM.isBooted() &&
                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
        boolean switching = currentAltHashing ^ useAltHashing;
        if (switching) {
            hashSeed = useAltHashing
                ? sun.misc.Hashing.randomHashSeed(this)
                : 0;
        }
        return switching;
    }

第二种构造函数,向HashMap添加元素的方法

private void putAllForCreate(Map<? extends K, ? extends V> m) {
    for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
        putForCreate(e.getKey(), e.getValue());
}
private void putForCreate(K key, V value) {
    int hash = null == key ? 0 : hash(key);
    int i = indexFor(hash, table.length);//得到数组位置
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k)))) {
            e.value = value;
            return;
        }
    }
    createEntry(hash, key, value, i);
}
//新添Entry
void createEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<>(hash, key, value, e);
    size++;
}

链表节点:

    static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;//每组数据的键
        V value;//值
        Entry<K,V> next;//它指向的下一个节点指针
        int hash;//哈希值,意思是在表中的位置

        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

        public final K getKey() {
            return key;
        }

        public final V getValue() {
            return value;
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
            Object k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
                Object v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    return true;
            }
            return false;
        }

        public final int hashCode() {
            return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
        }

        public final String toString() {
            return getKey() + "=" + getValue();
        }

        void recordAccess(HashMap<K,V> m) {
        }

        void recordRemoval(HashMap<K,V> m) {
        }
    }

扩容:

   void resize(int newCapacity) {
        Entry[] oldTable = table;  
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }

        Entry[] newTable = new Entry[newCapacity];
        transfer(newTable, initHashSeedAsNeeded(newCapacity));//原先数据赋值给新建的Entry[]
        table = newTable;
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }

    void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
        for (Entry<K,V> e : table) {//table是HashMap存储的数组
            while(null != e) {
                Entry<K,V> next = e.next;
                if (rehash) {//是否需要重新计算hash
                    e.hash = null == e.key ? 0 : hash(e.key);
                }
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            }
        }
    }

添加:

   public V put(K key, V value) {
        if (table == EMPTY_TABLE) {//如果没有初始化
            inflateTable(threshold);//初始化hashmap 包括创建hashMap保存的元素的数组等
        }
        if (key == null)//Key为null时放在0位置
            return putForNullKey(value);
        int hash = hash(key);//使用Key计算hash值
        int i = indexFor(hash, table.length);//使用hash值和数组长度计算在Entry[]中的位置
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {//遍历table[i]位置的链表
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//如果Key存在在Hashmap中,会代替原先value值
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);//,如果Key不存在hashmap中,则添加到Map方法中
        return null;
    }
indexFor计算Entry[]中的存储位置:
    static int indexFor(int h, int length) {
        // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
        return h & (length-1);
    }

:
addEntry:

    void addEntry(int hash, K key, V value, int bucketIndex) { //bucketIndex  Entry[]数组的索引
        if ((size >= threshold) && (null != table[bucketIndex])) {
            resize(2 * table.length);  //扩容,数据重新计算位置放入hashMap
            hash = (null != key) ? hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);
        }
        //添加到HashMap
        createEntry(hash, key, value, bucketIndex);
    }
    void createEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<>(hash, key, value, e);//将新添加的Entry的next元素指向table[bucketIndex]第一个元素;也就是新添加的放在链头
        size++;
    }

获取:

    public V get(Object key) {
        if (key == null)    //key为null返回table[0]中key为null的值
            return getForNullKey();
        Entry<K,V> entry = getEntry(key);

        return null == entry ? null : entry.getValue();
    }
    final Entry<K,V> getEntry(Object key) {//根据key获取对应的Entry[]
        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[indexFor(hash, table.length)];   //遍历该位置单链表,根据Key判断
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }

移除:

    public V remove(Object key) {
        Entry<K,V> e = removeEntryForKey(key);
        return (e == null ? null : e.value);
    }
    final Entry<K,V> removeEntryForKey(Object key) {//先根据hash获取位置table[i],然后遍历单链表获取
        if (size == 0) {
            return null;
        }
        int hash = (key == null) ? 0 : hash(key);
        int i = indexFor(hash, table.length);
        Entry<K,V> prev = table[i];
        Entry<K,V> e = prev;

        while (e != null) { //prev->e->next
            Entry<K,V> next = e.next;
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k)))) {
                modCount++;
                size--;
                if (prev == e)//如果是table[i]的第一个元素,则把该单链表第二个元素提为第一
                    table[i] = next;
                else        
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }

        return e;
    }

HashIterator:

    private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;        // 下一个Entry
        int expectedModCount;   // 快速失败机制使用,每次使用Iterator时都会判断该值是否与modCount比较是否相等,不等说明其他线程修改了该HashMap就会fail-fast
        int index;              // 当前位置索引
        Entry<K,V> current;     // 当前位置Entry数据
        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)//在构造器会找到数组中第一个不是指向null的那个元素,将这个元素存入next中,同时index指向这个 数组元素的下一个下标
                    ;
            }
        }

        public final boolean hasNext() {
            return next != null;
        }

        final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();

            if ((next = e.next) == null) {//如果到达链表(桶)的结尾
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)//找到table数组中下一个不是指向空”链表“的那个元素,使next更新为”链表“首结点,同时更新index
                    ;
            }
            current = e;
            return e;
        }

        public void remove() {
            if (current == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Object k = current.key;
            current = null;
            HashMap.this.removeEntryForKey(k);
            expectedModCount = modCount;
        }
    }

Serializable序列化方法

// 将HashMap的“总的容量,实际容量,所有的Entry”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
    throws IOException
{

    s.defaultWriteObject();

    if (table==EMPTY_TABLE) {
        s.writeInt(roundUpToPowerOf2(threshold));
    } else {
       s.writeInt(table.length);
    }

    s.writeInt(size);

    if (size > 0) {
        for(Map.Entry<K,V> e : entrySet0()) {
            s.writeObject(e.getKey());
            s.writeObject(e.getValue());
        }
    }
}

private void readObject(java.io.ObjectInputStream s)
     throws IOException, ClassNotFoundException
{
    s.defaultReadObject();
    if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
        throw new InvalidObjectException("Illegal load factor: " +loadFactor);
    }


    table = (Entry<K,V>[]) EMPTY_TABLE;

    // Read in number of buckets
    s.readInt(); // ignored.


    int mappings = s.readInt();
    if (mappings < 0)
        throw new InvalidObjectException("Illegal mappings count: " + mappings);


    int capacity = (int) Math.min(
                mappings * Math.min(1 / loadFactor, 4.0f),HashMap.MAXIMUM_CAPACITY);

    // allocate the bucket array;
    if (mappings > 0) {
        inflateTable(capacity);
    } else {
        threshold = capacity;
    }

    init();  // Give subclass a chance to do its thing.

    // Read the keys and values, and put the mappings in the HashMap
    for (int i = 0; i < mappings; i++) {
        K key = (K) s.readObject();
        V value = (V) s.readObject();
        putForCreate(key, value);//创建entry放入数组
    }
}

keySet(),values(),和entrySet()是怎么实现的呢?
其实三个实现迭代器迭代都是依据HashIterator。
首先看keySet()方法

    public Set<K> keySet() {
        Set<K> ks = keySet;
        //如果为空则new一个KeySet
        return (ks != null ? ks : (keySet = new KeySet()));
    }

KeySet在HashMap中私有。

    private final class KeySet extends AbstractSet<K> {
        public Iterator<K> iterator() {
            return newKeyIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsKey(o);
        }
        public boolean remove(Object o) {
            return HashMap.this.removeEntryForKey(o) != null;
        }
        public void clear() {
            HashMap.this.clear();
        }
    }

在私有类KeySet的Iterator()方法中返回一个new KeyIterator。
在另外两个values,EntrySet类中,和KeySet区别也只是iterator()返回的迭代器不同。

    Iterator<K> newKeyIterator()   {
        return new KeyIterator();
    }
private final class KeyIterator extends HashIterator<K> {
    public K next() {
        return nextEntry().getKey();
    }
}

该迭代器继承HashIterator,只实现next()方法,说明该类的数据也就是用的HashIterator。
另外两个迭代器:

    private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
        public Map.Entry<K,V> next() {
            return nextEntry();
        }
    }
        private final class ValueIterator extends HashIterator<V> {
        public V next() {
            return nextEntry().value;
        }
    }

keySet和values和entrySet本质既然一样,就可以通过封装其相同的部分(也就是这里的HashIterator),再各自实现最重要的next方法。
nextEntry()方法是HashIterator中的final方法,用于返回Entry。
然后keySet和values的迭代器分别从中获取key和value。

       final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();

            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            current = e;
            return e;
        }

可见,对于迭代器的操作,其实都是根据底层的table来实现的,也就是直接操作键值对。在得到Entry之后再获得它的key或者value。正因为如此,迭代器的底层直接根据table进行操作,所以如果有别的容器持有了这个迭代器内部类,就可以直接实现同步中的可见性:对HashMap的改变体现在table,而传递出去的内部类可以访问table。

HashMap遍历
(1)

Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
    entry.getKey();
    entry.getValue();
}

(2)

Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, String> entry = iterator.next();
    entry.getKey();
    entry.getValue();
}

(3)

Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
    map.get(key);
}

HashMap的线程是不安全的,可以使用如下变成线程安全的Map
Map m = Collections.synchronizedMap(new HashMap(…));
多线程环境中推荐是ConcurrentHashMap

Thanks:
http://blog.youkuaiyun.com/u011240877/article/details/68939826
http://www.cnblogs.com/skywang12345/p/3310835.html
http://www.cnblogs.com/dsj2016/p/5551059.html
http://blog.youkuaiyun.com/liubin119712/article/details/51052283

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值