jdk源码阅读之HashMap(二)

HashMap的遍历

HashMap对应有三种遍历方式,分别是条目遍历(可理解为节点遍历)、键遍历、值遍历.

//遍历键的迭代器
final class KeyIterator extends HashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().key; }
    }
//遍历值的迭代器
    final class ValueIterator extends HashIterator
        implements Iterator<V> {
        public final V next() { return nextNode().value; }
    }
//遍历条目的迭代器
    final class EntryIterator extends HashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry<K,V> next() { return nextNode(); }
    }
//HashIterator是上面三个Iterator的基类,有上面三种迭代器的共同方法
abstract class HashIterator {
        Node<K,V> next;        // next entry to return
        Node<K,V> current;     // current entry
        int expectedModCount;  // for fast-fail
        int index;             // current slot

        HashIterator() {
            expectedModCount = modCount;
            Node<K,V>[] t = table;
            current = next = null;
            index = 0;
            if (t != null && size > 0) { // advance to first entry
                do {} while (index < t.length && (next = t[index++]) == null);
            }
        }

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

        final Node<K,V> nextNode() {
            Node<K,V>[] t;
            Node<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {} while (index < t.length && (next = t[index++]) == null);
            }
            return e;
        }

        public final void remove() {
            Node<K,V> p = current;
            if (p == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            current = null;
            K key = p.key;
            removeNode(hash(key), key, null, false, false);
            expectedModCount = modCount;
        }
    }

具体遍历的方法:

HashMap<String, String> hashMap = new HashMap<>();
		hashMap.put("Mike", "1000");
		hashMap.put("John", "6000");
		hashMap.put("Q", "10000");
		//获取迭代器的方法
		Iterator<Entry<String, String>> it = hashMap.entrySet().iterator();
		while (it.hasNext()) {
			Entry<String, String> next = it.next();
			String value = next.getValue();
			String key = next.getKey();
			System.out.println(key + "--" + value);
		}

看完HashMap的源代码,并没有一个方法直接获取EntryIterator 的实例,而是先通过entrySet方法先获取一个Set容器,通过这个容器获取迭代器.为什么不直接写一个方法获取EntryIterator 的实例,而要通过Set容器获取呢,源码里面的解释是这样的:

	/*
     * @return a set view of the mappings contained in this map
     *

上面的解释意思是:通过entrySet方法返回这个map的一个视图,相当于就是你在遍历这个map的时候,以为在遍历一个Set,在map上面覆盖了一层Set.
实际上set和map直接有一些共同之处,看过HashSet源码就知道,HashSet底层就是利用HashMap实现的。
下面贴出EntrySet的源码,相应KetSet、ValueSet源码可一样获取

public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
    }

    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        //通过该方法获取条目的迭代器,这里返回的元素是Map.Entry的迭代器,
        //其实HashMap的条目Node就是实现了Map.Entry
        public final Iterator<Map.Entry<K,V>> iterator() {
            return new EntryIterator();
        }
        public final boolean contains(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
            Object key = e.getKey();
            Node<K,V> candidate = getNode(hash(key), key);
            return candidate != null && candidate.equals(e);
        }
        public final boolean remove(Object o) {
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
                Object key = e.getKey();
                Object value = e.getValue();
                return removeNode(hash(key), key, value, true, true) != null;
            }
            return false;
        }
        public final Spliterator<Map.Entry<K,V>> spliterator() {
            return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
            Node<K,V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K,V> e = tab[i]; e != null; e = e.next)
                        action.accept(e);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    }

下面总结一下涉及到迭代器类的继承关系:

           |--> KeyIterator
HashIterator--> ValueIterator
           |--> EntryIterator
                   |--> KetSet
Set --> AbstractSet --> EnterySet  分别通过iterator方法获取对应的迭代器
                   |--> ValueSet

猜你喜欢

转载自blog.csdn.net/whoami_I/article/details/86252644