zoukankan      html  css  js  c++  java
  • Iterator-Java

    在Java中,Iterator的作用就是为了方便处理集合中的元素。例如获取和删除集合中的元素。

    在JDK8,Iterator接口提供了如下方法:

    迭代器Iterator最基本的两个方法是next()和hasNext()。其中Java迭代器多了一个remove()方法。在JDK8中又新增了forEachRemaining()方法。

    接下来,以ArrayList为例,看下迭代器在Java中的实现。

    在ArrayList中,以内部类的方式实现,每次调用iterator()方法,都会new Itr()。

    先看一下ArrayList迭代器的实现类:

    定义的参数如下:

    1 int cursor;       // 下标,默认值0;
    2 int lastRet = -1; //最后一个元素的下标,如果没有返回-1;
    3 int expectedModCount = modCount;//结构修改(添加、删除等操作)次数,默认值0;

    定义的方法如下:

    hasNext()方法: 

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

    当集合中不存在下一个元素,即已经遍历至集合末尾时,该方法返回false。hasNext 方法主要用于循环终止条件。

    next()方法:

     1 public E next() {
     2     checkForComodification();
     3     int i = cursor;
     4     if (i >= size)
     5         throw new NoSuchElementException();
     6     Object[] elementData = ArrayList.this.elementData;
     7     if (i >= elementData.length)
     8         throw new ConcurrentModificationException();
     9     cursor = i + 1;
    10     return (E) elementData[lastRet = i];
    11 }

    在执行next()方法时,会先执行checkForComodification()方法,做一个判断(检查所迭代的列表对象是否被修改过):

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

    在对集合进行迭代过程中,不允许出现迭代器以外的对元素的操作,因为这样会产生安全隐患,java会抛出异常并发修改异常(ConcurrentModificationException),普通迭代器只支持在迭代过程中的删除动作。

    如果在遍历ArrayList时,想添加元素和修改元素,可以调用List集合的特有迭代器ListIterator。

    remove()方法:

     1 public void remove() {
     2     if (lastRet < 0) throw new IllegalStateException();
     3     checkForComodification();
     4 
     5     try {
     6         ArrayList.this.remove(lastRet);
     7         cursor = lastRet;
     8         lastRet = -1;
     9         expectedModCount = modCount;
    10     } catch (IndexOutOfBoundsException ex) {
    11         throw new ConcurrentModificationException();
    12     }
    13 }

    Java普通迭代器中唯一支持修改结构的操作。在执行完删除操作后,会更新expectedModCount字段的值。

    forEachRemaining()方法:

     1 public void forEachRemaining(Consumer<? super E> consumer) {
     2     Objects.requireNonNull(consumer);
     3     final int size = ArrayList.this.size;
     4     int i = cursor;
     5     if (i >= size) {
     6         return;
     7     }
     8     final Object[] elementData = ArrayList.this.elementData;
     9     if (i >= elementData.length) {
    10         throw new ConcurrentModificationException();
    11     }
    12     while (i != size && modCount == expectedModCount) {
    13         consumer.accept((E) elementData[i++]);
    14     }
    15     // update once at end of iteration to reduce heap write traffic
    16     cursor = i;
    17     lastRet = i - 1;
    18     checkForComodification();
    19 }

    forEachRemaining()是JDK8中新增的方法。forEachRemaining()使用迭代器Iterator的所有元素,并且第二次调用它将不会做任何事情,因为不再有下一个元素。

    一个使用场景:获得对应集合的迭代器Iterator,然后您可以开始迭代,next()直到达到某个条件,然后使用forEachRemaining()操作该Iterator上的其余部分。

    接下来,看一下刚才提到的ListIterator。

    在普通的Iterator中,只能对元素进行获取(next())和删除(remove())的操作。而ListIterator提供了更多的方法:

    add(E e): 将指定的元素插入列表,插入位置为迭代器当前位置之前
    hasNext():以正向遍历列表时,如果列表迭代器后面还有元素,则返回 true,否则返回false
    hasPrevious():如果以逆向遍历列表,列表迭代器前面还有元素,则返回 true,否则返回false
    next():返回列表中ListIterator指向位置后面的元素
    nextIndex():返回列表中ListIterator所需位置后面元素的索引
    previous():返回列表中ListIterator指向位置前面的元素
    previousIndex():返回列表中ListIterator所需位置前面元素的索引

    在使用特有的迭代器时,我们就能做更多的操作了。

  • 相关阅读:
    PAT 1088 三人行
    memset和memcpy
    算法训练 结点选择
    算法训练 K好数
    算法训练 最大最小公倍数
    算法训练 区间k大数查询
    算法训练 Eurodiffusion
    Kubernetes Device Plugins
    Kubeadm and Kops
    Go语言包管理工具Glide
  • 原文地址:https://www.cnblogs.com/Darlin356230410/p/11278329.html
Copyright © 2011-2022 走看看