java集合类中的迭代器模式
不说模式的问题,看一个<<设计模式之禅>>里面的例子。
老板要看到公司了各个项目的情况。(我知道我这个概述很让人头大,看代码吧)
示例程序
v1
- package Iterator;
- /**
- * @author cbf4Life cbf4life@126.com
- * 定义一个接口,所有的项目都是一个接口
- */
- public interface IProject {
- //从老板这里看到的就是项目信息
- public String getProjectInfo();
- }
- package Iterator;
- /**
- * @author cbf4Life cbf4life@126.com
- * 所有项目的信息类
- */
- public class Project implements IProject {
- //项目名称
- private String name = "";
- //项目成员数量
- private int num = 0;
- //项目费用
- private int cost = 0;
- //定义一个构造函数,把所有老板需要看到的信息存储起来
- public Project(String name,int num,int cost){
- //赋值到类的成员变量中
- this.name = name;
- this.num = num;
- this.cost=cost;
- }
- //得到项目的信息
- public String getProjectInfo() {
- String info = "";
- //获得项目的名称
- info = info+ "项目名称是:" + this.name;
- //获得项目人数
- info = info + "\t项目人数: "+ this.num;
- //项目费用
- info = info+ "\t 项目费用:"+ this.cost;
- return info;
- }
- }
- package Iterator;
- import java.util.ArrayList;
- /**
- * @author cbf4Life cbf4life@126.com
- * 老板来看项目信息了
- */
- public class Boss {
- public static void main(String[] args) {
- //定义一个List,存放所有的项目对象
- ArrayList<IProject> projectList = new ArrayList<IProject>();
- //增加星球大战项目
- projectList.add(new Project("星球大战项目",10,10));
- //增加扭转时空项目
- projectList.add(new Project("扭转时空项目",100,1000));
- //增加超人改造项目
- projectList.add(new Project("超人改造项目",10000,100000));
- //这边100个项目
- for(int i=4;i<10;i++)
- projectList.add(new Project("第"+i+"个项目",i*5,i*100));
- //遍历一下ArrayList,把所有的数据都取出
- for(IProject project:projectList)
- System.out.println(project.getProjectInfo());
- }
- }
类图如下:
实在太简单了,没什么说的。
不过现在,我想提几个问题。
多个对象聚在一起形成的总体叫做聚集(Aggregate)。在java中就是实现了Collection接口的那些类。我们在学习c的时候就接触的数组就是最最基本的聚集,在java中,数组也是其他聚集类型的设计基础。
从1.2版本开始java就提供了多种聚集,Vector,ArrayList,Stack,LinkList,HashSet,TreeSet,HashMap,TreeMap等等。
数组,堆栈,散列表有多种存储结构,如果我不想有数组来存储工程信息了要换成散列表,上面的代码就得大改(其实,我得承认这个假设本身就有问题,很少会有人没事闲得慌改存储结构,我们只是举个例子,引出我们下面要说的问题)
我们希望,java中的各种聚集都能提供一种"迭代"的功能。
ok 看我们的下个版本
从图中能看到,我们已经使用了jdk提供的迭代器相关模块。
v2
- public interface Iterable<T> {
- Iterator<T> iterator();
- }
Iterable接口,任何能"具有迭代"功能的聚集都要实现这个接口,它也只有一个方法,返回聚集的迭代器。
- public interface Iterator<E> {
- boolean hasNext();
- E next();
- void remove();
- }
Iterator接口,就是具体的迭代器。
大家在理解迭代器模式的时候,不妨这样想,一个聚集能够遍历自身,之前是因为我们用for循环依次取出每个元素,现在引入了模式后,遍历的功能就交给迭代器这个类(接口)了。
现在看代码
- package iterator.v2;
- import java.util.ArrayList;
- import java.util.Iterator;
- /**
- * @author cbf4Life cbf4life@126.com
- * 定义一个迭代器
- */
- public class ProjectIterator implements Iterator<Object>{
- //所有的项目都放在这里ArrayList中
- private ArrayList<IProject> projectList = new ArrayList<IProject>();
- private int currentItem = 0;
- //构造函数出入projectList
- public ProjectIterator(ArrayList<IProject> projectList){
- this.projectList = projectList;
- }
- //判断是否还有元素,必须实现
- public boolean hasNext() {
- //定义一个返回值
- boolean b = true;
- if(this.currentItem>=projectList.size() || this.projectList.get(this.currentItem) == null){
- b =false;
- }
- return b;
- }
- //取得下一个值
- public IProject next() {
- return (IProject)this.projectList.get(this.currentItem++);
- }
- //删除一个对象
- public void remove() {
- //暂时没有使用到
- }
- }
- package iterator.v2;
- import java.util.Iterator;
- /**
- * @author cbf4Life cbf4life@126.com
- * 定义一个接口,所有的项目都是一个接口
- */
- public interface IProject extends Iterable<Object>{
- //增加项目
- public void add(String name,int num,int cost);
- //从老板这里看到的就是项目信息
- public String getProjectInfo();
- public Iterator<Object> iterator();
- }
- package iterator.v2;
- import java.util.ArrayList;
- import java.util.Iterator;
- /**
- * @author cbf4Life cbf4life@126.com
- * 所有项目的信息类
- */
- @SuppressWarnings("all")
- public class Project implements IProject {
- //定义一个项目列表,说有的项目都放在这里
- private ArrayList<IProject> projectList = new ArrayList<IProject>();
- //项目名称
- private String name = "";
- //项目成员数量
- private int num = 0;
- //项目费用
- private int cost = 0;
- public Project(){
- }
- //定义一个构造函数,把所有老板需要看到的信息存储起来
- private Project(String name,int num,int cost){
- ...
- }
- //增加项目
- public void add(String name,int num,int cost){
- this.projectList.add(new Project(name,num,cost));
- }
- //得到项目的信息
- public String getProjectInfo() {
- ...
- }
- //产生一个遍历对象
- public Iterator<Object> iterator(){
- return new ProjectIterator(this.projectList);
- }
- }
- package iterator.v2;
- /**
- * @author cbf4Life cbf4life@126.com
- * 老板来看项目信息了
- */
- public class Boss {
- public static void main(String[] args) {
- //定义一个List,存放所有的项目对象
- IProject project = new Project();
- //增加星球大战项目
- project.add("星球大战项目ddddd",10,100);
- //增加扭转时空项目
- project.add("扭转时空项目",100,10000);
- //增加超人改造项目
- project.add("超人改造项目",10000,1000000);
- //这边100个项目
- for(int i=4;i<14;i++){
- project.add("第"+i+"个项目",i*5,i*1000);
- }
- //遍历一下ArrayList,把所有的数据都取出
- ProjectIterator projectIterator = (ProjectIterator) project.iterator();
- while(projectIterator.hasNext()){
- IProject p = (IProject)projectIterator.next();
- System.out.println(p.getProjectInfo());
- }
- }
- }
迭代器模式的通用类图
图里面的具体迭代器与具体聚集之间的关系有点意思,这一点希望大家多看看代码。
另一方面,我们也可以把ProjectIterator作为内部类放置在projcet类里,这样迭代器就能直接访问到projectList。
后面我们这样改了之后再boss类里面
ProjectIterator projectIterator = (ProjectIterator) project.iterator();
代码依然可以用,这就是创建与使用分离的好处,也就是工厂模式的好处。
jdk的迭代器模式在聚集中的应用
uml图
在AbstractList中有以下两个方法
- public ListIterator<E> listIterator() {
- return new ListItr(0);
- }
- public Iterator<E> iterator() {
- return new Itr();
- }
不管是上面的uml图还是下面的代码,大家现在心里一定有个问题,ListItr与Itr是怎么回事。
其实我们只要看看AbstractList的源代码就能明白:Iterator接口里面的方法实在是太少了,hasNext,next,remove就三个方法;从遍历上来说也就是正向遍历,我要是想逆向遍历一下怎么办?ListItr就有这个功能
下面再看一段代码:
- import java.util.*;
- public class IteratorDemo {
- public static void process(Collection c) {
- Iterator i = c.iterator(); //创建迭代器对象
- //通过迭代器遍历聚合对象
- while(i.hasNext()) {
- System.out.println(i.next().toString());
- }
- }
- public static void main(String args[]) {
- Collection persons;
- persons = new ArrayList(); //创建一个ArrayList类型的聚合对象
- persons.add("张无忌");
- persons.add("小龙女");
- persons.add("令狐冲");
- persons.add("韦小宝");
- persons.add("袁紫衣");
- persons.add("小龙女");
- process(persons);
- }
- }
我们现在是用ArrayList来存储数据,要是想换成HashSet很简单,也就
persons = new HashSet<String>(); //创建一个ArrayList类型的聚合对象
一行代码的事。
下面还有一个问题,一个班级(Class in School)包含多个学生(Student),使用Java内置迭代器实现对学生信息的遍历,要求按学生年龄由大到小的次序输出学生信息。
怎么做,这个咱们下一节来讨论。
参考资料
java与模式
设计模式之禅 第二十章 迭代器模式
http://blog.csdn.net/lovelion/article/details/9992005 遍历聚合对象中的元素——迭代器模式 (很多资料都是参考自刘伟老师的博客)
java集合类中的迭代器模式的更多相关文章
- Java集合类中的哈希总结
JAVA集合类中的哈希总结 目 录 1.哈希表 2.Hashtable.HashMap.ConcurrentHashMap.LinkedHashMap.TreeMap区别 3.Hashtable.Ha ...
- Java设计模式系列之迭代器模式
迭代器模式定义 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示. 迭代器模式的角色构成 (1)迭代器角色(Iterator):定义遍历元素所需 ...
- Java设计模式学习记录-迭代器模式
前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...
- Java笔记20:迭代器模式
迭代器模式 所谓Iterator模式,即是Iterator为不同的容器提供一个统一的访问方式.本文以Java中的容器为例,模拟Iterator的原理. 1 定义一个容器Collection接口 pub ...
- 《JAVA设计模式》之迭代器模式(Iterator)
在阎宏博士的<JAVA与模式>一书中开头是这样描述迭代子(Iterator)模式的: 迭代子模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不 ...
- 重学 Java 设计模式:实战迭代器模式「模拟公司组织架构树结构关系,深度迭代遍历人员信息输出场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 相信相信的力量! 从懵懂的少年,到拿起键盘,可以写一个Hell ...
- Java设计模式8:迭代器模式
迭代器模式 迭代器模式又叫做游标(Cursor)模式,其作用是提供一种方法访问一个容器元素中的各个对象,而又不暴露该对象的内部细节. 迭代器模式结构 迭代器模式由以下角色组成: 1.迭代器角色 负责定 ...
- JAVA集合中的迭代器的遍历
JAVA中的迭代器,迭代实质上就是遍历,在JAVA中使用iterator()方法进行迭代.需要注意的是,iterator()方法的返回值是Iterator对象.Iterator对象有三个方法,hasN ...
- JAVA设计模式之【迭代器模式】
迭代器模式 聚合类,聚合对象 电视机遥控器,迭代器,遍历局和对象中的成员 灵活新增遍历方法 将负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历分离.这就是迭代器模式. 灵活性,可扩 ...
随机推荐
- Servlet - Listener、Filter、Decorator
Servlet 标签 : Java与Web Listener-监听器 Listener为在Java Web中进行事件驱动编程提供了一整套事件类和监听器接口.Listener监听的事件源分为Servle ...
- JAVA面向对象-----接口的特点
接口的特点 1.类实现接口可以通过implements实现,实现接口的时候必须把接口中的所有方法实现,一个类可以实现多个接口. 2.接口中定义的所有的属性默认是public static final的 ...
- Linux下yum安装MySQL yum安装MySQL指定版本
yum安装MySQL 1. 查看有没有安装过 yum list installed MySQL* (有存在要卸载yum remove MySQL*) rpm -qa | grep my ...
- Gradle 的Daemon配置
最近升级到Android 2.2.2之后,运行之前的项目特别卡,基本上2分钟,好的时候1分半,查询了Android官网的说明说daemon能够加快编译.于是我也尝试开启Daemon. 在Windows ...
- Dynamics CRM 依赖组件类型为应用程序功能区导致的无法删除实体问题的解决方法
看到有人问到这个问题,这边就简单描述下解决方法,主要是针对第一次碰到这个问题云里雾里的朋友,错误如下 在我们建lookup关联的时候有下图中的这么个设置,对于很多新手默认就是下图这样不会去做改动,因为 ...
- mac OS X 从无法同步互联网时间想到的
最近在mac OS X 巨浪 :)上执行 ntpdate time.nist.gov 失败,提示 13 Jan 19:41:53 ntpdate[1374]: the NTP socket is in ...
- 【一天一道LeetCode】#202. Happy Number
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Write a ...
- 15个易遗忘的java知识点
1.java中的基本数据类型以及所占内存大小 (1)整形 byte 1字节 short 2字节 int 4字节 long 8字节 (2)浮点型 float 4字节 double 8字节 ...
- 如何优化MySQL insert性能
对于一些数据量较大的系统,面临的问题除了是查询效率低下,还有一个很重要的问题就是插入时间长.我们就有一个业务系统,每天的数据导入需要4-5个钟.这种费时的操作其实是很有风险的,假设程序出了问题,想重跑 ...
- HTML5 placeholder(空白提示) 属性
原文地址:HTML5′s placeholder Attribute 演示地址: placeholder演示 原文日期: 2010年08月09日 翻译日期: 2013年8月6日 浏览器引入了许多的HT ...