现在的位置: 首页 > 综合 > 正文

Set接口的iterator方法源码探究

2012年11月17日 ⁄ 综合 ⁄ 共 1855字 ⁄ 字号 评论关闭

今天在学习nio的过程时,突然发现个小细节平时都没有注意到的,大家都知道Set接口中有一个iterator方法可以进行迭代,

不过估计很多人都没有太注意Iterator接口的remove方法,该方法将移除迭代器中最后一个元素(即当前迭代器指向的元素)。

那么我们在使用Set的iterator方法返回一个迭代器后,使用remove方法移除一个元素,原Set集合是否发生变化?

这只是写代码时的一个小细节,提醒还未注意到的朋友,已经了解的可以略过了。

接下来我们通过源码解决疑问。

先拿HashSet类来说:

该类实现了Set接口,维护一个HashMap对象,将set集合每一个元素作为map的key以保证集合中元素没有重复。

iterator方法实际返回map的keySet的迭代,需要注意的是该keySet不是HashSet类型的。

/**
     * Returns an iterator over the elements in this set.  The elements
     * are returned in no particular order.
     *
     * @return an Iterator over the elements in this set
     * @see ConcurrentModificationException
     */
    public Iterator<E> iterator() {
	return map.keySet().iterator();
    }

跟进HashMap类中,HashMap则是维护一个Entry数组来保存键值对,

打开eclipse的outline视图,你会发现HashMap中很多的内部类,我们需要关心的是HashIterator类,

HashIterator类是一个抽象类,有另外三个类分别继承了它,这三个类是ValueIterator,KeyIterator和EntryIterator,大家看名字就应该了解各自的作用了

这三个类呢,都只重写了next方法来满足各自的需求,而我们关注的remove方法则在抽象类HashIterator中

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

该方法只是获取当前的key值,然后交给HashMap的removeEntryForKey来处理

跟进去,一切明了

 /**
     * Removes and returns the entry associated with the specified key
     * in the HashMap.  Returns null if the HashMap contains no mapping
     * for this key.
     */
    final Entry<K,V> removeEntryForKey(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        int i = indexFor(hash, table.length);
        Entry<K,V> prev = table[i];
        Entry<K,V> e = prev;

        while (e != null) {
            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] = next;
                else
                    prev.next = next;
                e.recordRemoval(this);
                return e;
            }
            prev = e;
            e = next;
        }

        return e;
    }

总结:Set维护的是一个hashMap对象,iterator方法返回的是该hashMap对象的key集合的迭代(也就是HashMap$KeyIterator的对象),KeyIterator的remove方法由父类HashIterator实现,实际却是返回当前迭代的key值交与HashMap再做进一步处理,最终删除还是HashMap删除的,自然Set集合中的值也被删除了!

抓狂表达还是如此稀烂,看不懂的话大家自己跟进源码看看吧!!

抱歉!评论已关闭.