[集合类] 源码解析2(Iterator的实现)

Iterator源码分析

上一篇[集合类] 源码解析1(Iterable、RandomAccess、Serializable、Cloneable


分析都写在代码注释中了,希望大家耐心读。

1. 整体

接上一篇文章,这一篇我们来详细分析一下Iterator接口,以及常见的实现。下面是常用类的类图,没有Set是因为Set是一种特殊的Map,这个后面再说。

在这里插入图片描述

下面是接口定义,定义了迭代器的基本操作。

public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

  	// 暂时忽略
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

Iterator下面有两个抽象,一个是ListIterator,一个是HashIterator

2. ListIterator

我们查看ListIterator接口,它继承了Iterator接口,除了继承的方法,他还自己定义了一系列用于List的迭代器方法。

public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();
    E next();
   	void remove();
  /**************华丽的分割线**********************/ 
    boolean hasPrevious();
  
    E previous();
  
    int nextIndex();
  
    int previousIndex();
  
    void set(E e);
  
    void add(E e);
}

下面我们具体看一下各个类的实现

3. Vector

Vector是线程安全的动态增长的数组,就是线程安全的ArrayList。本文只分析其内部类Itr和ListItr,源码如下。

1)Itr

// 获取Itr对象
public synchronized Iterator<E> iterator() {
    return new Itr();
}

// 获取index元素
E elementData(int index) {
	  return (E) elementData[index];
}

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount; // 记录操作次数,用来支持 fast fail机制,在迭代时不能修改容器

    public boolean hasNext() {
      	// cursor == elementCount表示遍历到尾部
        return cursor != elementCount;
    }

    public E next() {
      	// 锁Vector对象,保证不同的线程使用不同的迭代器操作同一Vector,同步执行
        synchronized (Vector.this) {
          	// fast fail 机制,检查容器是否被修改
            checkForComodification();
            int i = cursor;
            if (i >= elementCount)
                throw new NoSuchElementException();
            cursor = i + 1;
          	// 获取下一个cursor,并设置lastRet
            return elementData(lastRet = i);
        }
    }

    public void remove() {
        if (lastRet == -1)
            throw new IllegalStateException();
      			// 同上
        synchronized (Vector.this) {
          		// 同上
            	checkForComodification();
          		// 调用Vector方法,并重新设置modCount
            	Vector.this.remove(lastRet);
            	expectedModCount = modCount;
        }
      	// 设置当前cursor 为lastRet,上次操作的索引。
        cursor = lastRet;
        lastRet = -1;
    }

    @Override
    public void forEachRemaining(Consumer<? super E> action) {
       // ...
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

2)ListItr

// 获取ListItr对象
public synchronized ListIterator<E> listIterator() {
    return new ListItr(0);
}

// 传入初始cursor值
public synchronized ListIterator<E> listIterator(int index) {
	  if (index < 0 || index > elementCount)
		    throw new IndexOutOfBoundsException("Index: "+index);
	  return new ListItr(index);
}

// 继承了Itr,所以拥有Itr的所有方法,这里只定义了ListIterator特有的方法。
final class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }
		
  	// 可以对比hasNext方法
    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }

  	// 对比next方法
    public E previous() {
      	// 同上
        synchronized (Vector.this) {
          	// 同上
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            cursor = i;
          	// 同样设置lastRet
            return elementData(lastRet = i);
        }
    }

  	// 设置上次遍历的值
    public void set(E e) {
        if (lastRet == -1)
            throw new IllegalStateException();
        synchronized (Vector.this) {
            checkForComodification();
            Vector.this.set(lastRet, e);
        }
    }
		
  	// 添加到cursor前一个位置
    public void add(E e) {
        int i = cursor;
        synchronized (Vector.this) {
            checkForComodification();
          	// 调用Vector方法,添加到cursor的位置,使用数组拷贝,将后面的元素向后移动
            Vector.this.add(i, e);
            expectedModCount = modCount;
        }
        cursor = i + 1;
        lastRet = -1;
    }
}

总结一下

  1. cursor为当前索引。
  2. lastRet为上次返回数据的索引,如果调用了add或remove方法,lastRet为-1。
  3. expectedModCount记录操作次数,为fast fail机制作准备,在迭代时不能并发修改容器。
  4. 同步方法要锁Vector类,保证不同的迭代器对象同步操作同一个Vector容器

4. ArrayList

ArrayList和Vector的迭代器实现基本相同,只是不支持并发访问,代码贴出来,大家看一下就好。

1)Itr

public Iterator<E> iterator() {
    return new Itr();
}

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    Itr() {}

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        // ...
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

2) ListItr

public ListIterator<E> listIterator(int index) {
	  if (index < 0 || index > size)
  		  throw new IndexOutOfBoundsException("Index: "+index);
 		return new ListItr(index);
}

public ListIterator<E> listIterator() {
  	return new ListItr(0);
}

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }

    @SuppressWarnings("unchecked")
    public E previous() {
        checkForComodification();
        int i = cursor - 1;
        if (i < 0)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i;
        return (E) elementData[lastRet = i];
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.set(lastRet, e);
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            ArrayList.this.add(i, e);
            cursor = i + 1;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

5. LinkedList

1)ListItr

// 大家应该记得LinkedList继承了抽象类AbstractSequentialList 抽象顺序列表
// java.util.AbstractSequentialList
public Iterator<E> iterator() {
  	return listIterator();
}

public ListIterator<E> listIterator(int index) {
	  checkPositionIndex(index);
  	return new ListItr(index);
}

// Node
private static class Node<E> {
  	E item;
  	Node<E> next;
  	Node<E> prev;

  	Node(Node<E> prev, E element, Node<E> next) {
    		this.item = element;
    		this.next = next;
    		this.prev = prev;
  	}
}

// 定位第index个节点
Node<E> node(int index) {
  	// index在前一半,从前往后遍历,反之从后往前遍历
  	// 使用位运算,size / 2
  	if (index < (size >> 1)) {
    		Node<E> x = first;
    		for (int i = 0; i < index; i++)
      		x = x.next;
    		return x;
  	} else {
    		Node<E> x = last;
    		for (int i = size - 1; i > index; i--)
      		x = x.prev;
    		return x;
  	}
}


private class ListItr implements ListIterator<E> {
    private Node<E> lastReturned; // 上一个返回的节点
    private Node<E> next; // 下一个准备返回的节点,可以理解为当前节点
    private int nextIndex; // 同样,下一个准备返回的索引,可以理解为当前索引
    private int expectedModCount = modCount; // 维护操作次数

    ListItr(int index) {
        next = (index == size) ? null : node(index);
        nextIndex = index;
    }

  	// ArrayList中使用的是 != 符号
  	// ArrayList中的cursor和LinkedList的nextIndex的操作只有++ 和 -- ,两个类的作者都是同一个人
  	// 实在不知道这两种写法有什么区别,或者说真的就是没有区别,望大神指点。
    public boolean hasNext() {
        return nextIndex < size;
    }

    public E next() {
      	// fast fail机制,后面就不再提了
        checkForComodification();
        if (!hasNext())
            throw new NoSuchElementException();
				// 更新lastReture next nextIndex
        lastReturned = next;
        next = next.next;
        nextIndex++;
        return lastReturned.item;
    }

  	// 参考hasNext方法
    public boolean hasPrevious() {
        return nextIndex > 0;
    }

    public E previous() {
        checkForComodification();
        if (!hasPrevious())
            throw new NoSuchElementException();
				
      	// next == null 说明初始化index为size ->查看构造函数
        lastReturned = next = (next == null) ? last : next.prev;
        nextIndex--;
        return lastReturned.item;
    }

    public int nextIndex() {
        return nextIndex;
    }

    public int previousIndex() {
        return nextIndex - 1;
    }

    public void remove() {
        checkForComodification();
        if (lastReturned == null)
            throw new IllegalStateException();
      
        Node<E> lastNext = lastReturned.next;
      	// 将lastreturned节点从链表中脱离出来
      	unlink(lastReturned);

      	// 如果之前调用previous方法,next == lastReturned,移除的是当前节点,则让当前引用指向下一个节点
      	// 否则之前调用的是next方法,lastReturned.next == next,移除的是next的前一个节点,则将当前索引减1
        if (next == lastReturned)
            next = lastNext;
        else
            nextIndex--;
      
      	// 清除引用,方便GC
        lastReturned = null;
        expectedModCount++;
    }

  	// 设置lastReturned节点的值
    public void set(E e) {
        if (lastReturned == null)
            throw new IllegalStateException();
        checkForComodification();
        lastReturned.item = e;
    }

    public void add(E e) {
        checkForComodification();
        lastReturned = null;
        // 说明初始化index为size, 添加到链表尾
        if (next == null)
            linkLast(e);
        else
        // 添加到当前节点的前面
            linkBefore(e, next);
        nextIndex++;
        expectedModCount++;
    }

    public void forEachRemaining(Consumer<? super E> action) {
        // ...
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

下面总结一下各个方法做了什么:

  1. next方法:将当前节点的值返回,更新当前节点、当前索引,记录lastReturned
  2. previous方法:如果初始化index为size,则将当前节点和lastReturned都指向最后一个节点。否则将当前节点和lastReturned都指向当前节点的前驱节点。将索引值减1.
  3. remove方法:删除lastReturned指向的节点。如果当前节点next也指向被删除的节点,则将next指向下一个节点,否则当前索引减1.
  4. set方法:比较简单,直接修改lastReturned指向的节点的值
  5. add方法:如果初始化index为size,则添加到链表尾部,否则添加到当前节点的前面。当前索引+1.

2)DescendingIterator

Descending Iterator 翻译成中文是 下降迭代器。顾名思义,他是反向遍历的迭代器,只是对ListItr进行了简单的封装,源码如下。

public Iterator<E> descendingIterator() {
    return new DescendingIterator();
}

private class DescendingIterator implements Iterator<E> {
    private final ListItr itr = new ListItr(size());
    public boolean hasNext() {
        return itr.hasPrevious();
    }
    public E next() {
        return itr.previous();
    }
    public void remove() {
        itr.remove();
    }
}

6. PriorityQueue

PriorityQueue相比其他容器,存在 删除节点时节点上浮到已经遍历的位置 的问题。重点是使用forgetMeNot队列保存上浮的节点,最后遍历,代码如下。

public Iterator<E> iterator() {
    return new Itr();
}

private final class Itr implements Iterator<E> {
		// 当前索引
    private int cursor = 0;
    // 上一个返回的索引
    private int lastRet = -1;
   	// 在remove方法中,调用Vector的removeAt方法。
  	// removeAt方法中会将最后一个节点替换到被删除的元素的位置
  	// 然后进行下沉操作siftDown,如果没有执行,说明当前节点比子节点都大
  	// 这时进行上浮操作siftUp,如果节点上浮,说明当前节点比父节点小
  	// 即当前节点上浮到已经遍历过的位置,此时使用forgetMeNot队列保存节点,最后再遍历
    private ArrayDeque<E> forgetMeNot = null;
		// 上一个返回的节点
    private E lastRetElt = null;
  	// 同上,fast fail机制
    private int expectedModCount = modCount;

    public boolean hasNext() {
      	// 首先判断索引是否超过size,没有直接返回,一定有next
        return cursor < size ||
          	// 索引超过size后,查看forgetMeNot队列
          	// 有节点说明在之前remove时,有上浮到已经遍历过的位置的节点,返回true
            (forgetMeNot != null && !forgetMeNot.isEmpty());
    }

    @SuppressWarnings("unchecked")
    public E next() {
        if (expectedModCount != modCount)
            throw new ConcurrentModificationException();
      
        if (cursor < size)
            return (E) queue[lastRet = cursor++];
      	
      	// 索引超过size后,查看forgetMeNot队列中是否有剩余的,在之前remove时上浮到已经遍历过的位置的节点
      	// 有则继续遍历forgetMeNot队列
        if (forgetMeNot != null) {
            lastRet = -1;
          	// 记录上一个返回节点
            lastRetElt = forgetMeNot.poll();
            if (lastRetElt != null)
                return lastRetElt;
        }
        throw new NoSuchElementException();
    }

    public void remove() {
        if (expectedModCount != modCount)
            throw new ConcurrentModificationException();
        if (lastRet != -1) { 
          	// 后面PriorityQueue类专题会分析removeAt方法
          	// 方法会将最后一个节点替换到被删除的位置,再进行下沉、上浮
          	// 通过返回值来说明是否上浮,不为null说明上浮了,返回目标节点
            E moved = PriorityQueue.this.removeAt(lastRet);
            lastRet = -1;
          
          	// moved == null说明最后一个节点替换到被删除位置后没有上浮
            if (moved == null)
                cursor--;
          	// 否则,说明节点上浮到已经遍历的位置,就将节点加到队列中,等待最后遍历
            else {
                if (forgetMeNot == null)
                    forgetMeNot = new ArrayDeque<>();
                forgetMeNot.add(moved);
            }
          
        } else if (lastRetElt != null) {
          	// 进入这里,说明上一次遍历是遍历forgetMeNot队列,则不存在上浮的问题
          	// 通过遍历找到目标节点索引,调用removeAt删除。(方法实现在本段代码最后)
            PriorityQueue.this.removeEq(lastRetElt);
            lastRetElt = null;
        } else {
            throw new IllegalStateException();
        }
      	// 删除节点,修改操作次数
        expectedModCount = modCount;
    }
}

boolean removeEq(Object o) {
  for (int i = 0; i < size; i++) {
    if (o == queue[i]) {
      removeAt(i);
      return true;
    }
  }
  return false;
}

7. HashMap

HashMap中Key、Value封装成Entry保存,所以遍历时有三种方式,Key、Value和Entry。HashMap使用HashIterator用来实现基本遍历操作,再用KeyIterator、ValueIterator和EntryIterator封装next方法。

static class Node<K,V> implements Map.Entry<K,V> {
  final int hash;
  final K key;
  V value;
  Node<K,V> next;
	// 省略方法...
}

abstract class HashIterator {
  	// 其实可以把next理解成当前节点,current理解成lastReturned节点,像之前那样
    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
          	// 初始化next,找到第一个不为空的桶,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();
      	// ******************核心***********************
      	// 更新current的值为next,next为更新后current的next
      	// 如果next为空,说明当前桶遍历完毕,进入下一个
        if ((next = (current = e).next) == null && (t = table) != null) {
          	// 找到下一个不为空的桶,next引用其第一个节点
            do {} while (index < t.length && (next = t[index++]) == null);
        }
      	// ******************核心***********************
        return e;
    }

  	// 移除current节点
    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;
      	// 调用HashMap的removeNode方法
        removeNode(hash(key), key, null, false, false);
        expectedModCount = modCount;
    }
}

// 下面是获取迭代器的方法

// HashMap.KeySet
public final Iterator<K> iterator() { 
  	return new KeyIterator(); 
}

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

// HashMap.Values
public final Iterator<V> iterator() { 
  	return new ValueIterator(); 
}

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

// HashMap.entrySet
public final Iterator<Map.Entry<K,V>> iterator() {
  	return new EntryIterator();
}

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

8. TreeMap

abstract class PrivateEntryIterator<T> implements Iterator<T> {
    Entry<K,V> next; // 当前节点
    Entry<K,V> lastReturned; // 上一个返回的节点
    int expectedModCount; // 操作次数 fast fail机制

    PrivateEntryIterator(Entry<K,V> first) {
        expectedModCount = modCount;
        lastReturned = null;
        next = first;
    }

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

    final Entry<K,V> nextEntry() {
        Entry<K,V> e = next;
        if (e == null)
            throw new NoSuchElementException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
      	// 找到后继节点
        next = successor(e);
        lastReturned = e;
        return e;
    }

    final Entry<K,V> prevEntry() {
        Entry<K,V> e = next;
        if (e == null)
            throw new NoSuchElementException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
      	// 找到前驱节点
        next = predecessor(e);
        lastReturned = e;
        return e;
    }

    public void remove() {
        if (lastReturned == null)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
      	// 删除上一个返回的节点
      	// 如果他有一个孩子,则子树则会替代他的位置
      	// 如果他有两个孩子,则会使其后继节点(右子树的最左孩子)替代他的位置,就需要调整next引用到lastReturned
        // deleted entries are replaced by their successors
        if (lastReturned.left != null && lastReturned.right != null)
            next = lastReturned;
        deleteEntry(lastReturned);
        expectedModCount = modCount;
        lastReturned = null;
    }
}


// 下面是获取迭代器的方法

// TreeMap.EntrySet
public Iterator<Map.Entry<K,V>> iterator() {
	  return new EntryIterator(getFirstEntry());
}

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

// TreeMap.Values
public Iterator<V> iterator() {
		return new ValueIterator(getFirstEntry());
}

final class ValueIterator extends PrivateEntryIterator<V> {
    ValueIterator(Entry<K,V> first) {
        super(first);
    }
    public V next() {
        return nextEntry().value;
    }
}

Iterator<K> keyIterator() {
	  return new KeyIterator(getFirstEntry());
}

final class KeyIterator extends PrivateEntryIterator<K> {
    KeyIterator(Entry<K,V> first) {
        super(first);
    }
    public K next() {
        return nextEntry().key;
    }
}

Iterator<K> descendingKeyIterator() {
	  return new DescendingKeyIterator(getLastEntry());
}

final class DescendingKeyIterator extends PrivateEntryIterator<K> {
    DescendingKeyIterator(Entry<K,V> first) {
        super(first);
    }
    public K next() {
        return prevEntry().key;
    }
    public void remove() {
        if (lastReturned == null)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        deleteEntry(lastReturned);
        lastReturned = null;
        expectedModCount = modCount;
    }
}

下一篇:[集合类]源码解析3(Collection接口和AbstractCollection抽象类)

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值