前不久听一大神讲课,期间提到Iterator,别看它方法简单,可是组装起来就像“数据加工厂”一样!

下面详细一记
首先略介绍一下Iterator的三个主要方法:

next()获得序列中的下一个元素。

hasNext()检查序列中是否还有元素。

remove()将迭代器新返回的元素删除。

数据加工厂主要用到的是next()和hasNext()这两个方法,拿下面这个问题来说

<问题>

linux下有很多对文本进行操作的命令,比如cat filename 可以将文件的所有内容输出到控制台上。

grep keyword filename可以将文件内容中包含keyword的行内容输出到控制台上。

wc -l filename可以统计filename文件中的行数。

|是代表管道的意思,管道左边命令的结果作为管道右边命令的输入,比如cat filename | grep exception | wc -l,可以用来统计一个文件中exception出现的行数。

请实现一个功能,可以解析一个linux命令(只包含上面三个命令和上面提到的参数以及和管道一起完成的组合,其它情况不考虑),比如下面这几个例子:

cat xx.txt

cat xx.txt | grep xml

wc -l xx.txt

cat xx.txt | grep xml | wc --l

</问题>

上面这个问题是要对一个数据源进行几种不同的处理,

第一种思路大致如下:

首先把输入的命令分割成单个的命令,然后根据命令的功能编写处理数据的功能模块,遍历命令列表,对数据处理,将结果记录,作为下一个命令的传入参数,直到所有命令执行完毕。

优点:灵活性不错,各种命令可以很方便地组合成不同的功能,扩展性也很好,需要增加新的命令的时候只需要编写新的功能模块就行了,执行的主流程几乎不用修改。

缺点:需要留存中间结果,也就是说当数据源过大的时候就无能为力了,另外,如果处理数据的中途出现意外,那么即使你已经完成绝大部分工作,到最后还是什么结果也不会得到。

第二种思路:流水线工厂,使用Iterator的特点来实现:(hasNext()判断是否有下一条数据,next()取出下一条数据,下面提到的每个Iterator都将反复用到这两个方法)

首先,将数据源(上面的问题里是文件)构造成Iterator;1

然后对每个命令编写各自的迭代器构造函数,各自实现hasNext和next,传入参数为Iterator,返回为Iterator;2

接着,根据输入的命令来拼接每个Iterator,得到最终的结果result(同样是Iterator);3

最后,输出result。4

上面的操作步骤中,123都没有对数据源进行任何操作,只是构造出了一套处理逻辑,最后的第4步看似是输出结果,其实在这一步里面数据才被加工。

优点:包含第一种思路的所有优点,而且第一种思路的缺点也得到解决,数据源任意大(因为内存里面永远只有当前正在处理的一行),而且即使中途出现问题,出现问题之前的正常数据也会得到正常的处理并且输出。

缺点:需要一直占用数据源的read句柄,其实占用的时间虽然比上一种方法长,也长不了多少

第一种方法占用的时间为:数据长度*(一次io时间 + 做一次处理的时间)

第二种方法占用的时间为:数据长度*(一次io时间 + 做多次处理的时间)

一般来说io时间是远大于处理时间的,因此占用时间其实是长不了多少的。

下面看第二种方法的代码:

主流程,根据命令构造一套处理逻辑

//result用于记录最后一个迭代器
Iterator<String> result = null;
for (String command : commands) {
List<String> args = splitter.omitEmptyStrings().splitToList(command);
if (result == null) {
//第一次执行的时候,result为空,需要对源文件进行处理得到源文件的迭代器
result = new FileIterator(new File(args.get(args.size() - 1)));
}
//根据命令名对相应的迭代器进行初始化
result = commandMap.getObject(args.get(0)).init(args, result);
}
return result;//构造文件迭代器FileIteratorprivate BufferedReader reader;
private String line = null;public FileIterator(File file) throws FileNotFoundException {
reader = Files.newReader(file, Charsets.UTF_8);
}@Override public boolean hasNext() {
try {
line = (line == null) ? reader.readLine() : line;
} catch (IOException e) {
LOGGER.error("readLine() error", e);
}
if (line == null) {
IOHandler.closeIgnoreException(reader);
}
return line != null;
}@Override public String next() {
try {
String temp = (line == null) ? reader.readLine() : line;
line = null;
if(temp == null){
IOHandler.closeIgnoreException(reader);
}
return temp;
} catch (IOException e) {
LOGGER.error("readLine() error", e);
}
return null;
}//Grep命令的迭代器(其他的差不多,就不贴了)private String filter;
private String line = null;private void getLine() {
String temp;
while (line == null) {
if (!parent.hasNext()) {
break;
}
temp = parent.next();
if (temp.contains(filter)) {
line = temp;
break;
}
}
}@Override public boolean hasNext() {
getLine();
return line != null;
}@Override public String next() {
getLine();
String result = line;
line = null;
return result;
}@Override public Iterator<String> init(List<String> args, Iterator<String> parent) {
this.parent = parent;
filter = args.get(1);
return this;
}

注:上面的代码都只是一部分,只是方便参看。

/*****************************2015-09-21*****************************/

重看这篇,当时主要是为了实践和体会老师介绍的一种方法,现在回头看,要做这个功能的话,没有必要用Iterator,功能方面是没问题,但是编码方面逻辑比较分散,后来维护的人比较难读。不如就用一个Queue,读到命令行时初始化queue,存入的类继承同一个接口,接口里设定处理方法和初始化方法,各命令类实现,初始化完成后得到一个处理逻辑的队列,读每一行遍历处理就好了。

当然之前的也是Iterator接口的一种使用方式,在合适的地方用合适的接口吧。

转载于:https://www.cnblogs.com/just84/p/4805386.html

java学习:Iterator数据加工厂相关推荐

  1. python本科生就业_准备报学习机构学习大数据、Java或者python,是计算机专业的本科生,请问选择哪种就业发展比较好?...

    谢邀.对比java和python后者还算是小语种.不知道楼主的具体情况如何.根据个人情况,建议先学java,毕竟你目前的需求是尽快找到更合适的技术工作,java择业面相对较宽,虽然也难学,但学习资源丰 ...

  2. Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与Lin

    1.容器API的类图结构如下: JAVA的集合类是一种特别有用的工具类,它可以用于存储数量不等的多个对象,并可以实现常用数据结构,如栈,队列等,除此之外,JAVA集合还可用于保存具有映射关系的关联数组 ...

  3. 什么是java的元数据_学习大数据,为什么要先学习Java?

    是新朋友吗?记得先点蓝字关注我哦- 今日课程菜单 Java全栈开发 | Web前端+H5 大数据开发 | 数据分析  人工智能+Python | 人工智能+物联网 来源:小职(z_zhizuobiao ...

  4. 为何学习大数据,要先学Java

    大数据的就业.工资的水平等等方面都让更多的人投身进入到学习大数据的旗下.在我之前写文章的时候,其实总是有这样的粉丝问我,你的这文章和大数据有关系?发出了这样的质疑. 其实,我们也不难发现,在外面报班学 ...

  5. 零基础是学习Java还是大数据?

    大数据 可不是零基础就可以培训出来的,它是需要在特定环境下才能进行的,没有多少公司需要大数据的岗位,这个东西门槛很高. 说实话,我是不建议你直接报班学大数据的,但凡有点常识的人都知道,大数据的工作是已 ...

  6. 学习大数据的第13天——Java面向对象(接口、分析参数返回值的类型不同时如何解决、包以及访问权限修饰符(public、protected、默认、private))

    学习大数据的第13天--Java面向对象(接口.分析参数返回值的类型不同时如何解决.包以及访问权限修饰符(public.protected.默认.private)) 接口 接口的基本定义: 1.1.语 ...

  7. java转大数据的学习路线

    不要错过文末彩蛋] 申明: 本文旨在为普通程序员(Java程序员最佳)提供一个入门级别的大数据技术学习路径,不适用于大数据工程师的进阶学习,也不适用于零编程基础的同学. 前言: 一.背景介绍 二.大数 ...

  8. 初学者大数据java学习路线从入门到精通

    大数据时代的出现简单的讲是海量数据同完美计算能力结合的结果,确切的说是移动互联网.物联网产生了海量的数据,大数据计算技术完美地解决了海量数据的收集.存储.计算.分析的问题.当我们最初谈大数据的时候,谈 ...

  9. java 与大数据学习较好的网站

    C# C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿! https://www.cnblogs.com/doforfuture/p/6293926.htm ...

最新文章

  1. 近期Freecodecamp问题总结
  2. 第01章 PyTorch简介和安装 的学习笔记
  3. Centos7升级python
  4. docker 登陆mysql_启用登录docker mysql容器
  5. 重庆一银行发生火灾 浓烟直往外窜
  6. 使用 Castal DynamicProxy 简化 Silverlight 数据绑定
  7. GItHub--Makedown语法学习(快速入门)
  8. 阿里云数据库开源发布:PolarDB三节点高可用的功能特性和关键技术
  9. linux设备驱动模块引用和依赖
  10. linux开机自启动python脚本_Linux下Python脚本自启动和定时启动的详细步骤
  11. 快速上手Spring WebFlux框架
  12. 计算机win10+上锁,手把手教你在windows 10右键菜单中添加Bitlocker上锁/解锁教程-网络教程与技术 -亦是美网络...
  13. 岁月温柔-3 清明节医院复查,去昆明过冬是否会是一种奢望?
  14. 【记录】在新电脑安装Ubuntu16.04系统并移植虚拟机中catkin_ws过程
  15. python中复数的实部和虚部都是浮点数_Python基础:数值(布尔型、整型、长整型、浮点型、复数)...
  16. 27种迹象你该考虑辞掉程序员的工作
  17. 文心一言——何妨吟啸且徐行
  18. 流程二备选方案及评估
  19. 人生的极致:大道至简 知行合一
  20. java jsoup jar包_jsoup jar包

热门文章

  1. oracle剩余月份计算,[HELP]如何计算两个日期之间的月份(非MONTHS_BETWEEN)?
  2. 使用elementui实现表单上传功能_使用ElementUI中的upload组件上传Excel文件
  3. 网络推广外包介绍网站该如何加快收录量?
  4. 网站SEO优化该如何提高用户粘度?
  5. 网站页面内链如何布局才更有利于SEO?
  6. 搜索引擎蜘蛛为什么对网站不爬行呢?
  7. 某一列高度变化_高度近视,老了后会瞎吗?
  8. 记一次EventBus内存泄露导致的项目问题
  9. 大数据平台安全标准设计
  10. 超线程技术——超线程技术让(P4)处理器增加5%的裸晶面积,就可以换来15%~30%的效能提升,本质单核模拟双核!和异步编程的思想无异。...