JAVA非并发容器--HashMap-迭代器

概述

我相信只要写过JAVA的程序要拿99%的都用过HashMap, 其是我们最常用,也是最基础的一个Map.本篇文章将从存储结构、hash规则、扩容策略、迭代器四方面来分析其源代码。
HashMap的迭代起需要记住几个规则:
1:所有迭代器底层共享一份数据,就是那个table表,无论你用何种迭代琦(key的,value的或是entry的)或实例化多少格迭代器,每个迭代器操作的数据都只有一份.
2:无论何种迭代器,底层都是hash迭代器
3:迭代出来的顺序与put进去的顺序是无序的

迭代器的实现

private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;        // next entry to return
        int expectedModCount;   // For fast-fail
        int index;              // current slot
        Entry<K,V> current;     // current entry

        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }

        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)
                    ;
            }
            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;
        }
    }

由上面的代码可知,hash迭代器保存当前entry和下一个entry,同时记录当前的数组index, expectedModCount表示存储结构更新了多少次,用此来实现快速失败规则。
三种迭代器:

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

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

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

快速失败规则

在HashMap中有一个变量

transient int modCount;

记录着这个hashmap结构变化(put,remove)过多少次, 当你新建一个迭代器时,迭代器copy了一份,当你操作迭代器的时候,每次都对比expectedModCount和modConunt是否相等,如果不相等,就失败。
用一句话就是说:在你使用一个迭代器操作map的时候,不要用另外一个迭代器或是其它方式改变map的结构

    原文作者:米途小码
    原文地址: https://www.jianshu.com/p/53a5443783ef
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞