一、基本概念

迭代器是一个对象,也是一种设计模式,Java有两个用来实实现迭代器的接口,分别是Iterator接口和继承自Iterator的ListIterator接口。实现迭代器接口的类的对象有遍历集合对象,选择集合中的元素和删除集合中元素的方法。而在使用它时不必知道该集合对象底层的结构。Java类库中实现Iterator接口的迭代器只能正向遍历集合中的元素,而实现ListIterator接口的迭代器不仅能够正向遍历,还能够反向遍历集合中的元素。

二、源码分析

2.1、Iterator接口与ListIterator接口的继承与实现

图2.1  Java迭代器类的继承与接口实现(部分)

ListIterator接口继承了Iterator接口。在AbstractList、ArrayList和Vector这三个类中的内部类ListItr实现了ListIterator接口,这三个类的内部类ListItr又分别继承了在这三个类中实现了Iterator接口的内部类Itr。实现ListIterator的类还有LinkedList的内部类ListItr。实现Iterator的类还有LinkedList的内部类DescendingIterator,HashMap的内部类EntryIterator,KeyIterator,ValueIterator,以及TreeMap的内部类PrivateEntryIterator等。

2.2、迭代器接口方法

       

        1)迭代器的向前移动与向后移动图解

         2)Iterator接口方法

  1. package java.util;
  2.  
  3. import java.util.function.Consumer;
  4.  
  5. public interface Iterator<E> {
  6.  
  7. boolean hasNext();
  8.  
  9. /* 在Java中,这个方法的具体实现一般用来在遍历容器时,调用该方法使迭代器向前移动一位,来检测集合中是否还有下一个元素,还有下一个元素返回true,否则返回false*/
  10.  
  11. E next();
  12.  
  13. /* 实现这个方法,在遍历容器时,调用该方法将迭代器向前移动一位,并将迭代器越过的一个元素作为方法的返回值。该方法用来返回集合中下一个元素。
    在调用next()方法前,先调用hasNext()方法判断集合中是否还有下一个元素 */
  14.  
  15. default void remove() { throw new UnsupportedOperationException("remove"); }
  16.  
  17. /* 实现这个方法,用来删除在迭代器调用next()方法迭代器越过的一个元素*/
  18.  
  19. default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); }
  20.  
  21. /* 实现这个方法来顺序遍历容器中的每个元素,用来实现集合类的ForEach遍历操作*/
    }

       3)ListIterator接口方法

  1. package java.util;
  2.  
  3. public interface ListIterator<E> extends Iterator<E> {
  4.  
  5. boolean hasNext();//同Iterator接口,用来检测迭代器前面是否还有元素
  6.  
  7. E next();
  8.  
  9. // 同Iterator接口,使迭代器向前移动一位,获得迭代器越过的下一个元素
  10.  
  11. boolean hasPrevious();
  12.  
  13. // 实现这个方法来检测当前迭代器位置后面是否有元素,用于反向遍历
  14.  
  15. E previous();
  16.  
  17. /* 实现这个方法,将迭代器向后移动一位,并将迭代器越过的后面的一个元素作为方法返回值,在调用该方法前需要调用hasPrevious方法来判断迭代器前是否有元素 */
  18.  
  19. int nextIndex();//实现该方法获取迭代器前面一个元素的索引
  20.  
  21. int previousIndex();//实现该方法获取迭代器后面一个元素的索引
  22.  
  23. void remove();
  24.  
  25. /* 实现该方法,用来删除迭代器调用next()方法或调用previous()方法时迭代器越过的一个元素 */
  26.  
  27. void set(E e);//实现该方法在迭代器遍历时修改元素
  28.  
  29. void add(E e);//实现该方法在迭代器遍历时添加元素
  30. }

2.3、容器类与迭代器的关系

       1)Iterator接口。阅读源码可知,Collectiion接口实现了Iterable接口,Iterable有一个返回一个Iterator<T>对象的iterator()方法,所以继承和实现了Collection接口的所有容器类及其子类和实现类都有一个返回Iterator对象的的iterator()方法。Java中有很多容器类中都设计有实现了Iterator接口的内部类,如ArrayList和LinkedList等类。HashMap和TreeMap类中也包含有实现了Iterator的内部类,来对Map中的KeySet、Value和EntrySet进行迭代。Iterable接口的源代码如下:

  1. public interface Iterable<T> {
  2.  
  3. Iterator<T> iterator();//实现这个方法,该方法返回一个Iterator迭代器对象。
  4.  
  5. default void forEach(Consumer<? super T> action) {
  6. Objects.requireNonNull(action);
  7. for (T t : this) {
  8. action.accept(t);
  9. }
  10. }//实现这个方法来对容器进行ForEach遍历
  11.  
  12. default Spliterator<T> spliterator() {
  13. return Spliterators.spliteratorUnknownSize(iterator(), 0);
  14. }
  15. }

      

2)ListIterator接口。查看源码可以发现,List接口中有两个返回ListIterator<T>对象的方法,如下。List接口下的的ArrayList和LinkedList都有返回ListIterator对象的方法。

  1. ListIterator<E> listIterator();//实现这个方法,该方法返回一个ListIterator迭代器对象,迭代器初始化后,一般迭代器位于在容器第一个元素后面。
  2.  
  3. ListIterator<E> listIterator(int index);//实现这个方法,返回一个指定了开始遍历容器时迭代器初始位置的ListIterator迭代器对象
  • ArrayList类设计有实现了ListIterator接口的内部类ListItr(不过ArrayList的listIterator(final int index)方法并未使用这个内部类,而是在方法中又设计了一个ListIterator匿名内部类作为方法返回值,可以发现ArrayList的Iterator()方法也是调用了这个方法来构建迭代器对象)。ArrayList类中部分有关源码如下
  1. private class ListItr extends Itr implements ListIterator<E> {
  2. ListItr(int index) {
  3. super();
  4. cursor = index;
  5. }
  1. public Iterator<E> iterator() {
  2. return listIterator();
  3. }
  4.  
  5. public ListIterator<E> listIterator(final int index) {
  6. checkForComodification();
  7. rangeCheckForAdd(index);
  8. final int offset = this.offset;
  9.  
  10. return new ListIterator<E>() {//返回了一个ListIterator匿名内部类
  11. int cursor = index;
  12. int lastRet = -1;
  13. int expectedModCount = ArrayList.this.modCount;
  14.  
  15. public boolean hasNext() {
  16. return cursor != SubList.this.size;
  17. }
  • LinkedList类也有一个内部类ListItr实现了ListIterator接口,LinkedList的listIterator()方法返回了这个内部类的实例。LinkedList中部分有关源码如下
  1. public ListIterator<E> listIterator(int index) {
  2. checkPositionIndex(index);
  3. return new ListItr(index);
  4. }
  5.  
  6. private class ListItr implements ListIterator<E> {

(小官原创,若有谬误,望各位前辈批评指正)

Java容器类源码分析之Iterator与ListIterator迭代器(基于JDK8)的更多相关文章

  1. Java容器类源码分析前言之集合框架结构(基于JDK8)

    一.基本概念 Java容器类库的用途是"保存对象",容器库类分为两个不同的分支. 1.Collection.可以保存一个或多个对象,将其保存为一个序列.Collection又可以细 ...

  2. java集合源码分析(三):ArrayList

    概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...

  3. java集合源码分析(六):HashMap

    概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...

  4. Java Reference 源码分析

    @(Java)[Reference] Java Reference 源码分析 Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使 ...

  5. Java 集合源码分析(一)HashMap

    目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...

  6. Java集合源码分析(六)TreeSet<E>

    TreeSet简介 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, j ...

  7. Java集合源码分析(五)HashSet<E>

    HashSet简介 HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null元素. HashSet源 ...

  8. Java集合源码分析(三)LinkedList

    LinkedList简介 LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈.队列和双端队列来使用. LinkedList同样是非线程安全 ...

  9. Java集合类源码分析

    常用类及源码分析 集合类 原理分析 Collection   List   Vector 扩充容量的方法 ensureCapacityHelper很多方法都加入了synchronized同步语句,来保 ...

随机推荐

  1. python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别

    os._exit() 和 sys.exit() os._exit() vs sys.exit() 概述 Python的程序有两中退出方式:os._exit(), sys.exit().本文介绍这两种方 ...

  2. handoop安装部署集群

    hdfs 1.0版本 一个namenode (secordary namenode 2.0冷备份) 和多个datanode构成分布式文件系统 mapreduce 一个 jobtracker 协调 ta ...

  3. windows server防火墙添加例外的步骤

      Windows Server 2012 防火墙如何添加端口例外的方法 在Windows Server 2012系统中,如果用户想在防火墙中开通一个端口,您可以按以下步骤执行: 1. 首先点击桌面左 ...

  4. 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, VerticalAlignment

    [源码下载] 背水一战 Windows 10 (75) - 控件(控件基类): FrameworkElement - 基础知识, 相关事件, HorizontalAlignment, Vertical ...

  5. 剑指offer编程题Java实现——面试题8旋转数组的最小数字

    剑指offer面试题8:旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1, ...

  6. Android 音乐(音效)播放方式总结

    一.音效的分类 音效按照作用的不同,可以将音效分为即时音效和背景音乐.两种音效在Android中的实现技术是不同的. 主要的实现方式为:SoundPool.MediaPlayer. 区别在于,Medi ...

  7. [CocoaPods]客户端加载第三方库

    请先阅读另一篇博文铺垫知识基础:[CocoaPods]终端方式集成第三方库 客户端的Github地址:CocoaPods-app 点击下载客户端: [CocoaPods客户端] 安装下载的文件.软件界 ...

  8. 小鬼难缠--python小bug备忘

    今天编译pyhon做人脸识别,遇到几个问题,做个记录吧. 编译报错: File "harrClassifier.py", line 17, in <module> fl ...

  9. centos7防火墙管理的变化

    当我们在centos7中输入service iptables status 查看系统的防火墙状态,会出现如下错误: 网上查阅才知道centos7的防火墙管理工具变了,原来的iptables已经不用了, ...

  10. Caffe 使用记录(五):math_functions 分析

    本文转载自 Caffe源码(一):math_functions 分析 math_function 定义了caffe 中用到的一些矩阵操作和数值计算的一些函数,这里以float类型为例做简单的分析 1. ...