JAVA学习笔记--迭代器
迭代器(Iterator)是一种设计模式。它是一个对象,它的工作是遍历并选择序列中的对象,而客户端程序员不必知道或关心该序列底层的结构。创建迭代器的代价小,因而迭代器通常被称为轻量级对象。
一、Iterable
接口Iterable<T>,是Collection<E>等接口的超级接口。实现这个接口允许对象成为 foreach 语句的目标。
import java.util.iterator;
public interface Iterable<T>{
Iterator<T> iterator(); // 返回一个在一组T类型的元素上进行迭代的迭代器
}
二、Iterator
接口Iterator<E>,是对Collection进行迭代的迭代器。
方法:Iterator<E> iterator(); // 返回在此collection元素上进行迭代的迭代器,元素返回的顺序没有保证
JAVA的Iterator只能单向移动。使用方法iterator()要求容器返回一个在该collection上进行迭代的迭代器,Iterator将准备好返回序列中的第一个元素。
package com.tongye.iterator;
import java.util.*;
public class IteratorExample {
public static void main(String[] args){
List<String> list = new ArrayList<String>(); // 创建一个接收String类型元素的列表
list.add("my"); // 向list中添加元素
list.add("name");
list.add("is");
list.add("tongye");
System.out.println(list); // 打印列表
Iterator iter = list.iterator(); // 调用iterator()方法返回一个在list上进行迭代的迭代器
while(iter.hasNext()){ // 用hasNext()方法判断列表中是否还有元素
System.out.println(iter.next()); // 用next()方法返回迭代器迭代的下一个元素
iter.remove(); // 用remove()方法删除迭代器返回的最新的一个元素
}
System.out.println(list); // 打印列表
}
}
/* output:
[my, name, is, tongye]
my
name
is
tongye
[]
*/
可以看到,迭代器可以遍历并选择序列中的对象,这看起来和foreach语句很像,而所有的collection都可以用foreach来遍历。当我们只是需要向前遍历collection而不需要修改collection本身时,foreach语法会显得比较实用,但如果我们需要在遍历期间修改collection,像是删除操作,则不能用foreach语法,会抛出异常,因为在使用for循环的期间调用remove()的话会改变 list.size(),从而导致了错误。这时,使用迭代器进行遍历会比较好。
当然,迭代器的功能不仅仅只是遍历。迭代器能够将遍历序列的操作与序列底层的结构分离,达到很好的解耦效果,因此,我们也说:迭代器统一了对容器的访问方式。下面用一个例子演示一下迭代器的这个功能:
package com.tongye.iterator;
import java.util.*;
public class IteratorExample {
// printIterator方法用一个对一组String类型元素进行迭代的迭代器作为形参,方法体对迭代器进行遍历,
// 这是所有对String类型元素进行迭代的迭代器都可以使用的功能,而且代码是完全相同的
public static void printIterator(Iterator<String> iter){
while(iter.hasNext()){ // 判断迭代器是否还有元素
System.out.print(iter.next() + " "); // 打印迭代器迭代的下一个元素
}
System.out.println();
}
public static void main(String[] args){
List<String> list = new ArrayList<String>(); // 创建一个接收String类型元素的列表
list.add("my"); // 向list中添加元素
list.add("name");
list.add("is");
list.add("tongye");
printIterator(list.iterator()); // list.iterator()返回一个对list进行迭代的迭代器
Set<String> set = new HashSet<String>(); // 创建一个接收String类型元素的set
set.add("my"); // 向set中添加元素
set.add("name");
set.add("is");
set.add("tongye");
printIterator(set.iterator());
Queue<String> queue = new LinkedList<String>(); // 创建一个接收String类型元素的队列
queue.add("my"); // 向queue中添加元素
queue.add("name");
queue.add("is");
queue.add("tongye");
printIterator(queue.iterator());
}
}
/* output:
my name is tongye
tongye name is my
my name is tongye
*/
可以看到,迭代器只负责遍历工作,而不关系序列是什么类型的,这样带来的好处是程序条理更为清晰,代码更为简洁。
三、ListIterator
ListIterator, 系列表迭代器,是Iterator的子类型,只能用于访问List类,但是功能更为强大。允许程序按任一方向遍历列表,迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator没有当前元素,它的光标位置始终位于调用previous()所返回的元素和调用next()所返回的元素之间。
1)Iterator只能单向移动,但是ListIterator可以双向移动;
2)可以产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引;
3)可以使用set()方法替换掉它访问过的最后一个元素。
下面的例子简单介绍了一下ListIterator的使用:
package com.tongye.iterator;
import java.util.*;
public class IteratorExample {
public static void main(String[] args){
Random rand = new Random(47);
List<String> list = new ArrayList<String>(); // 创建一个接收String类型元素的列表
list.add("my"); // 向list中添加元素
list.add("name");
list.add("is");
list.add("tongye");
ListIterator<String> iter = list.listIterator(); // 创建一个ListIterator
iter.add("hello"); // 在迭代期间调用add()方法插入元素
while(iter.hasNext()){ // hasNext()方法,正向遍历,如果list中还有元素,则返回true
System.out.print(iter.nextIndex() + ":"); // nextIndex()方法,返回对next的后续调用所返回元素的索引
System.out.print(iter.next() + " ");
}
System.out.println();
while(iter.hasPrevious()){ // hasPrevious()方法,逆向遍历,如果list中还有元素,则返回true
System.out.print(iter.previousIndex() + ":"); // previousIndex()方法,返回对previous的后续调用所返回元素的索引
System.out.print(iter.previous() + " ");
}
System.out.println();
while(iter.hasNext()){
iter.next();
iter.set(list.get(rand.nextInt(4))); // set()方法,用指定元素替换next或previous返回的最后一个元素
}
System.out.println(list);
}
}
/* output:
1:my 2:name 3:is 4:tongye
4:tongye 3:is 2:name 1:my 0:hello
[name, my, name, name, name]
* */
关于add()方法,用下面这张图来说明一下:ListIterator.add()方法可以在迭代期间向列表中添加元素,元素添加的位置是当前光标所在位置之前(next()所返回的下一个元素之前(如果有),previous()所返回的下一个元素之后(如果有))。因此,用add()添加一个元素,并不会影响插入的这一次遍历中对next()的后续调用,因此在上面的程序,第一次调用next()方法并没有输出添加的元素 hello;但是会对previous的后续调用有影响,添加的这个元素将是previous后续调用的第一个元素。

关于 ListIterator.set()方法,可以用指定元素替换 next 或 previous 返回的最后一个元素(可选操作),只有在最后一次调用 next 或 previous 后既没有调用ListIterator.add() 也没有调用 ListIterator.remove()是才可以进行该调用。
JAVA学习笔记--迭代器的更多相关文章
- java学习笔记11--集合总结
java学习笔记系列: java学习笔记10--泛型总结 java学习笔记9--内部类总结 java学习笔记8--接口总结 java学习笔记7--抽象类与抽象方法 java学习笔记6--类的继承.Ob ...
- Java学习笔记之---集合
Java学习笔记之---集合 (一)集合框架的体系结构 (二)List(列表) (1)特性 1.List中的元素是有序并且可以重复的,成为序列 2.List可以精确的控制每个元素的插入位置,并且可以删 ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- 0035 Java学习笔记-注解
什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...
- Java学习笔记(04)
Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...
- 0032 Java学习笔记-类加载机制-初步
JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
- 0028 Java学习笔记-面向对象-Lambda表达式
匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...
随机推荐
- CC2640R2F&TI-RTOS 拿到 TI CC2640R2F 开发板 第四件事就是 修改第三件事信号量超时改为 事件 超时,并增加 事件控制 ,用于控制LED 闪烁时间或者关闭
/* * data_process.c * * Created on: 2018年7月5日 * Author: admin */ #include "board_led.h" #i ...
- CodePush热更新组件详细接入教程
CodePush热更新组件详细接入教程 什么是CodePush CodePush是一个微软开发的云服务器.通过它,开发者可以直接在用户的设备上部署手机应用更新.CodePush相当于一个中心仓库,开发 ...
- EF结合SqlBulkCopy实现高效的批量数据插入 |EF插件EntityFramework.Extended实现批量更新和删除
原文链接:http://blog.csdn.net/fanbin168/article/details/51485969 批量插入 (17597条数据批量插入耗时1.7秒) using Sys ...
- Linux vi编辑器使用技巧
vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器.Linux中的vi编辑器叫vim,它是vi的增强版(vi Improved),与vi编辑器完全兼容,而且实现了很多增强功能. ...
- ps加强总结
快捷键 1.ctrl+alt+z返回 2.ctrl+z撤销 3.ctrl+s保存 4.ctrl+shift+s另存为 5.shift是有序的选择 ctrl键是无序的选择 6.ctrl+g打组 ...
- float(浮动)的属性和使用方法
1float浮动的属性值 left:向左浮动 right:向右浮动 2.当父元素未浮动,子元素浮动时,就会造成浮动塌陷 实例: 父元素: #mainDiv{ border: 5px solid red ...
- 大数据学习--day12(内部类)
内部类学习 定义在类的内部的类 叫做内部类 包含了内部类的类 叫做外部类 内部类的作用 内部类是为了 实现 java中 多继承而存在的 内部类 可以继承其他类 ...
- Chino 操作系统开发日志 (1) - 为 IoT 而生
引言 很多人都听说过 IoT (物联网)这个词,越来越多的人在装修时开始选择智能家居,很多人也购买智能音箱做智能家居控制,想必未来一定是 AI + 物联网的时代. 一种技术要发展并走向成熟必须要降低门 ...
- Java编码算法和摘要算法
编码算法 编码算法是将一种形式转换成等价的另外一种形式.主要是为了方便某种特定场景的处理. 字母如何在计算机中表示呢? 用ASCII编码 那中文字符如何在计算机中表示呢? 用Unicode编码 如何同 ...
- 07-容器类Widget
容器类Widget 容器类Widget一般只是包装其子Widget,对其添加一些修饰(补白或背景色等).变换(旋转或剪裁等).或限制(大小等) Padding Padding可以给其子节点添加补白(填 ...