码迷,mamicode.com
首页 > 其他好文 > 详细

HashMap中通过keySet遍历的顺序

时间:2020-07-16 18:08:10      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:his   调用   fail   imp   clear   map   count   asn   ons   

public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }

    final class KeySet extends AbstractSet<K> {
        public final int size()                 { return size; }
        public final void clear()               { HashMap.this.clear(); }
        public final Iterator<K> iterator()     { return new KeyIterator(); }
        public final boolean contains(Object o) { return containsKey(o); }
        public final boolean remove(Object key) {
            return removeNode(hash(key), key, null, false, true) != null;
        }
        public final Spliterator<K> spliterator() {
            return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
        }
        public final void forEach(Consumer<? super K> 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.key);
                }
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    }

以上是HashMap中ketSet的方法,以及KeySet类的源码

当第一次调用keySet时会创建一个对象,当遍历时会创建KeyIterator对象;这个对象是一个hashmap内部类

final class KeyIterator extends HashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().key; }
    }

继续调用HashIterator的nextNode()方法;HashIterator也是HashMap的内部类

 

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
     //这里可以看出next方法是按照数组的index从小到大遍历的
        HashIterator() {
            expectedModCount = modCount;
            Node<K,V>[] t = table;//存储node的数组;
            current = next = null;
            index = 0;
            if (t != null && size > 0) { // advance to first entry 为next节点赋值
                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;
        }
    }

 modCount != expectedModCount 这个判断的存在是为了不允许我们在遍历时通过hashmap的方法进行添加删除

modCount和expectedModCount 记录了map的修改次数

当通过haspmap修改时 HashIterator内部的expectedModCount 不会被修改;

 

 

 


       

 

HashMap中通过keySet遍历的顺序

标签:his   调用   fail   imp   clear   map   count   asn   ons   

原文地址:https://www.cnblogs.com/hanzhengjie/p/13324027.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!