HashMap源码浅析(三):迭代器Iterator

KeySet

我们在遍历HashMap的时候会用到keySet()获取到当前HashMap的key值的一个Set集合

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

可以看到直接创建了一个KeySet对象,final class KeySet extends AbstractSet,KeySet继承于AbstractSet
KeySet有几个方法:

size 返回当前HashMap的元素数量
clear 情况当前HashMap的元素
iterator 返回一个KeyIterator对象,用于遍历key值
contains 判断当前HashMap中是否包含有指定的key值
remove删除指定key值
forEach 遍历集合,每遍历一次返回一个key值

我们先来看iterator()
HashMap#KeySet#iterator():

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

KeyIterator继承于HashIteratorIterator,只有一个next()

KeyIterator

KeyIterator中的属性:

next 代表当前节点的下一个节点
current 代表当前节点
expectedModCount 代表修改次数 遍历期间不能对集合进行操作,否则expectedModeCount不一致会抛出异常
index 当前节点的下标

keyIterator中的方法

hasNext() 判断当前节点是否还有下一节点,即当前节点是否是尾节点
nextNode() 返回下一节点的node
remove() 删除当前节点

我们先来看构造器
HashMap#HashIterator#HashIterator():

        HashIterator() {
            expectedModCount = modCount;
            Node[] 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);
            }
        }

构造器中对属性进行了初始化,并通过while循环,得到数组中的第一个不为空的元素下标以及值,并将此元素值赋给next
HashMap#HashIterator#hasNext():

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

hasNext()判断当前元素是否有下个节点值,首次调用的话,next为构造器中首次遍历到的值
HashMap#HashIterator#nextNode():

        final Node nextNode() {
            Node[] t;
            Node 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;
        }

nextNode()获取遍历到的当前节点,也可以理解为hasNext()所判断的下一节点,主要是看最后一个判断,e为当前要返回的节点,获取e的下一节点,并赋值给next,如果此时的next为空,则说明当前链表已经遍历完毕,那么进入判断体,开始遍历下一个数组桶中的链表,并将此链表的头结点赋值给next;
remove()比较简单这里就不多说了。
说到这里我们结合KeySet整体总结一遍流程:

        HashMap hashMap = new HashMap<>();
        hashMap.put("w","c");
        hashMap.put("a","h");
        hashMap.put("n","u");
        hashMap.put("g","a");
        hashMap.put("c","n");
        Iterator iterator = hashMap.keySet().iterator();
        while (iterator.hasNext()){
            Log.i("chuan", "onResume: " + iterator.next());
        }

上面是通过KeySet对集合进行的遍历
首先我们通过keySet()获取到一个Set对象(虽然Set内部也是通过HashMap实现的,但是这里只是用到了HashMap的存储功能,并没有用到迭代器,否则就陷入了先有鸡还是先有蛋的死循环中)

    public Set keySet() {
        Set ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }
    
    public final Iterator iterator()     { return new KeyIterator(); }

然后通过KeySet中的iterator()获取到Iterator对象,

        final class KeyIterator extends HashIterator
            implements Iterator {
            public final K next() { return nextNode().key; }
        }
    
        public final boolean hasNext() {
            return next != null;
        }

        final Node nextNode() {
            Node[] t;
            Node 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;
        }

最后通过HashIteratorhashNext()nextNode()获取到下一节点
其实继承HashIterator的还有两个类,分别是获取valuenodeValueIteratorEntryIterator,逻辑都一样,都是先获取到指定的节点node,然后在分别获取key,value或是node

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

    final class ValueIterator extends HashIterator
        implements Iterator {
        public final V next() { return nextNode().value; }
    }

    final class EntryIterator extends HashIterator
        implements Iterator> {
        public final Map.Entry next() { return nextNode(); }
    }

你可能感兴趣的:(HashMap源码浅析(三):迭代器Iterator)