Iterator接口

public interface Iterator<E> {

    boolean hasNext();

    E next();

    void remove();
}

访问元素前需要使用hasNext进行判断是否有元素存在,如果有再通过next操作获取,直接使用next操作而不进行hasNext检测,当到达末尾时会抛出NoSuchElement异常

Iterator的remove操作

好久没有看JDK代码了,今天翻看Java Core看到迭代器里面的注意点,居然一点都回忆不起来了。先看如下代码:

        Iterator<String> iter = list.iterator();
String s = iter.next();
iter.remove();

那么这里iter.remove()删除的是哪个元素,删除的是列表中的第一个元素,通用一点来讲是迭代器上一次next()所返回的那个元素。又有如下代码:

        Iterator<String> iter = list.iterator();
String s = iter.next();
iter.remove();
iter.remove();

如果去实际运行的话会报:java.lang.IllegalStateException异常即,每次remove都应该有对应的一次next,其实就是两两配对的,remove的就是next返回的那个元素。

从AbstractList的源码中可以看到Iterator的一个基本实现:

 private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0; /**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1; /**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount; public boolean hasNext() {
return cursor != size();
} public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

可以看到有lastRet和cursor两个变量,前者用于代表next()操作返回的元素的索引,后者用于表示下一次next()调用是应该返回的元素的索引值。每当一次remove操作后lastRet就被清空了,同时cursor--,因为lastRet对应的元素在cursor前面,而此时其被remove了,那么cursor的值必然要减一。其实这里的迭代器实现都基本上被AbstractList的子类覆盖了,如LinkedList,ArrayList。前者不支持随机访问肯定不能用索引值作为获取元素的实现,否则迭代器效率就太低了。

ListIterator(extends Iterator<E>)

List接口除了继承Iterable接口外,还有几个额外的方法(listIterator)用来获取专门针对List的迭代器(即ListIterator)可以看一下LinkedList的迭代器实现:

private class ListItr implements ListIterator<E> {
private Node<E> lastReturned = null;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount; ListItr(int index) {
// assert isPositionIndex(index);
next = (index == size) ? null : node(index);
nextIndex = index;
} public boolean hasNext() {
return nextIndex < size;
} public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException(); lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
} public boolean hasPrevious() {
return nextIndex > 0;
} public E previous() {
checkForComodification();
if (!hasPrevious())
throw new NoSuchElementException(); 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;
unlink(lastReturned);
if (next == lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = null;
expectedModCount++;
} public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.item = e;
} public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

对于remove操作的思路大体一致只不过把lastRet换成了一个链表节点lastReturned,在每次remove后也会将其置位null。而在获取元素上不是像父类版本中的那样直接通过get(i)进行获取。迭代器会保存两个相邻的节点指针lastReturned和next。这样当元素被remove掉(lastReturned=null),当再次调用next时由于保存了next指针值,依然可以在链表中移动。

相比于Iterator接口ListIterator接口多了一个add方法,它会把元素放入到迭代器指向的next元素之前的位置,即下一个元素之前的位置。

Iterable接口

public interface Iterable<T> {

    /**
* Returns an iterator over a set of elements of type T.
*
* @return an Iterator.
*/
Iterator<T> iterator();
}

如Java Core上所述如果我们实现Iterable接口那么就可以在foreach循环中使用。如

class MyCollection implements Iterable<Integer> {

    @Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
public int count = 0; @Override
public boolean hasNext() { return count < 10;
} @Override
public Integer next() {
return count++;
} @Override
public void remove() {
throw new UnsupportedOperationException();
} };
} } public class Fields implements Const {
public static void main(final String[] args) { MyCollection myCollection = new MyCollection();
for (Integer i : myCollection) {
System.out.println(i);
} }
}

Java 集合:迭代器(Iterator, Iterable)的更多相关文章

  1. Java集合迭代器 Iterator分析

    简介 迭代器是遍历容器的一种常用方法,它屏蔽了容器的实现细节,无需暴露数据结构内部,就可以对容器进行遍历,迭代器本身也是一种设计模式,迭代是一种特殊的遍历方式. Iterator 在java中,迭代器 ...

  2. java集合---迭代器iterator

    一:ArraryList  最终继承超级接口Collection,Colection接口继承Iterator接口. public interface Collection<E> exten ...

  3. Java集合(二)--Iterator和Iterable

    Iterable: public interface Iterable<T> { Iterator<T> iterator(); } 上面是Iterable源码,只有一个ite ...

  4. java 集合框架(二)Iterable接口

    Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...

  5. java集合迭代器

    一.Java中有一个设计模式是迭代器模式 1.迭代器模式定义迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 2.迭代器模式概述Java集合框 ...

  6. 集合迭代器Iterator

    迭代器模式:就是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节. 什么是迭代器Iterator? Java集合框架的集合类,我们有时候称之为容器.容器的种类有很多种,比 ...

  7. Java 实现迭代器(Iterator)模式

    类图 /** * 自己定义集合接口, 相似java.util.Collection * 用于数据存储 * @author stone * */ public interface ICollection ...

  8. Java 集合、Iterator迭代器、泛型等

    01集合使用的回顾 A:集合使用的回顾 a.ArrayList集合存储5个int类型元素 public static void main(String[] args) { ArrayList<I ...

  9. Java集合、Iterator迭代器和增强for循环整理

    集合 集合,集合是java中提供的一种容器,可以用来存储多个数据. 数组的长度是固定的.集合的长度是可变的.集合中存储的元素必须是引用类型数据 1.1      ArrayList集合存储元素 pac ...

  10. Java中迭代器Iterator的使用

    Java集合类中Map接口下的相关类并没有像Collection接口的相关类一样实现get()方法,因此在要实现遍历输出的场景中没法直接用get()方法来取得对象中的数据,但Java本身提供了另一种遍 ...

随机推荐

  1. Spring Boot 入门系列

    本系列博文版权 简书 面皮大师 所有,转载请标明原文及出处: http://www.jianshu.com/u/062bd8f1299c 项目地址: https://github.com/daleiw ...

  2. [性能分析]linux文件描述符

    1.什么是文件和文件描述符 Linux中文件可以分为4种:普通文件.目录文件.链接文件和设备文件.1.普通文件是用户日常使用最多的文件,包括文本文件.shell脚本.二进制的可执行和各种类型的数据.l ...

  3. 总结day3 ---- 进制转换,字符串切片,字符串常用方法.,for 循环,

    前情提要: int 的相关操作 进制转换 bit_lenth() str 的索引,以及常用的相关方法 for 循环 索引 切片 相关方法 一  : int 的相关操作 int 主要用于生活中的计算问题 ...

  4. java日期时间

    字母 日期或时间元素 表示 示例 G Era 标志符 Text AD y 年 Year 1996; 96 M 年中的月份 Month July; Jul; 07 w 年中的周数 Number 27   ...

  5. 5、Tensorflow基础(三)神经元函数及优化方法

    1.激活函数 激活函数(activation function)运行时激活神经网络中某一部分神经元,将激活信息向后传入下一层的神经网络.神经网络之所以能解决非线性问题(如语音.图像识别),本质上就是激 ...

  6. jQuery 节点操作(创建 插入 删除 复制 替换 包裹)

    一,创建元素节点: 第1个步骤可以使用jQuery的工厂函数$()来完成,格式如下: $(html); $(html)方法会根据传入的HTML标记字符串,创建一个DOM对象,并将这个DOM对象包装成一 ...

  7. 思科设备配置DHCP服务

    路由器,三层交换机都是可以做DHCP服务的,下面以Cisco 3750G-24TS-S为例配置DHCP服务,指令如下: ip dhcp pool DHCP-Server network 192.168 ...

  8. 认识python正则模块re

    python正则模块re python中re中内置匹配.搜索.替换方法见博客---python附录-re.py模块源码(含re官方文档链接) 正则的应用是处理一些字符串,phthon的博文python ...

  9. 谈谈数据库的ACID

    一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. // 创建 ...

  10. PHP加密解密数字,适用于URL加密。

    本博主最近正在建设一个9元包邮的网站,希望各位光临指导一些意见: 9元包邮 http://www.jiubaou.com/ <?php /** * 加密解密类 * 该算法仅支持加密数字.比较适用 ...