Scala中Iterator允许执行一次
背景
使用spark执行mapPartitionsWithIndex((index,iterator)=>{....}),在执行体中将iterator进行一次迭代后,再次根据iterator执行迭代,iterator迭代体未执行。
猜想及验证过程
猜测iterator只能执行一次迭代。
测试例子如下:
val rdd1 = sc.makeRDD(1 to 10,2)
val rdd2 = rdd1.mapPartitionsWithIndex{(index,iterator)=>{
var result = List[String]()
var sum = 0
var count = 0
while(iterator.hasNext){
sum += iterator.next()
}
while(iterator.hasNext){
count += 1
}
result.::(index + "|" + sum + "|" + count).iterator
}}
执行结果
res0: Array[String] = Array(0|15|0, 1|40|0)
通过执行结果可以看出sum执行了求和运算,count没有执行统计数量运算或未正确执行统计数量运算,推测可能的原因:1. iterator能够重复执行迭代,但是count的算术运算出现问题;2.iterator只能执行一次迭代;
对原因1的验证例子:
val rdd1 = sc.makeRDD(1 to 10,2)
val rdd2 = rdd1.mapPartitionsWithIndex{(index,iterator)=>{
var result = List[String]()
var sum = 0
var count = 0
while(iterator.hasNext){
sum += iterator.next()
count += 1
}
result.::(index + "|" + sum + "|" + count).iterator
}} 执行结果
res0: Array[String] = Array(0|15|5, 1|40|5)
如果iterator能够重复执行迭代,但是count的统计数量计算出现问题,那么将sum和count放在同一个迭代体中,执行结果会和在两个迭代体中执行结果一致。但是执行结果却是能够正常的统计出数量,证明了推测原因1不成立。
对原因2的验证例子:
为了单纯的验证是iterator执行问题,下边的例子去掉了spark相关的函数
val iterator = Iterator(1,2,3,4,5,6,7)
var sum = 0
while(iterator.hasNext){
sum += iterator.next
}
println("sum is " + sum)
val expression = if(iterator.isEmpty) "iterator is empty" else "iterator is not empty"
println(expression)
如果iterator只能执行一次迭代的话,expression的结果是【iterator is empty】,真实执行结果如下
sum is 28
iterator is empty
iterator: Iterator[Int] = empty iterator
sum: Int = 28
expression: String = iterator is empty
通过执行结果可以看出,expression的结果确实是【iterator is empty】,所以推测原因2成立。
结论
scala中iterator只能执行一次迭代,如果需要多次执行同一个迭代体,建议调用iterator.toList等方法,将迭代体转化为集合,再执行上述的验证例子就会正常。
扩展
1.iterator.min和iterator.max同样是通过迭代获得,所以对于同一个iterator的min和max只能获取一个。
2.java中Iterator类同scala的Iterator,只允许进行一次迭代,如果需要进行多次迭代,需要将iterator转化为集合类
3.C#中没有Iterator类,但是有IEnumerator,这个类可以通过IEnumerator.Reset方法来重置,迭代完进行重置就可以再次迭代,而对于java和scala的Iterator没有相似的方法;
补充
spark的mapPartitionsWithIndex中iterator尽量不要使用toList,原因:toList相当于将迭代数据进行了缓存,容易导致OutOfMemory的异常,iterator是流式的处理,处理完一条记录才会去读取下一条记录并且会丢弃已读的记录,无法重复使用;而iterator.toList会将所有的记录进行缓存,便于重复使用。
Scala中Iterator允许执行一次的更多相关文章
- shell 脚本中 while 只执行一次
实例代码 while read line ; do ssh -p20002 $line -o StrictHostKeyChecking=no xxxxxxxxx done < ip.txt w ...
- Crontab中shell每分钟执行一次HDFS文件上传不执行的解决方案
一.Crontab -e 加入输出Log */1 * * * * /qiwen_list/upload_to_hdfs.sh > /qiwen_list/mapred.log 2>& ...
- Unity中让Update中的方法执行一次
Unity中让Update中的方法执行一次 Unity中,很多时候,代码需要放在Update中时刻监测状态,一旦状态符合,又只需要代码执行一次:其实可以通过设置控制量的方式,让代码只执行一次:方法:设 ...
- express框架中如何只执行一次res响应操作
在做东西时候遇到一个可能会重复输出res.json的地方,重复输出会产生Error:Cannot set header after they are sent. Node.js不像c++里可以直接通过 ...
- pthread_once()使用(某个时间在整个程序中仅执行一次,不确定是那个线程)
在多线程环境中,有些事仅需要执行一次.通常当初始化应用程序时,可以比较容易地将其放在main函数中.但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread ...
- c++ 函数中的部分代码执行一次
编程时有时需要将一段代码中的某一块只执行一次: #include<iostream> using namespace std; int fun1(int a) { static bool ...
- selenium+python+unittest:一个类中只执行一次setUpClass和tearDownClass里面的内容(可解决重复打开浏览器和关闭浏览器,或重复登录等问题)
unittest框架是python自带的,所以直接import unittest即可,定义测试类时,父类是unittest.TestCase. 可实现执行测试前置条件.测试后置条件,对比预期结果和实际 ...
- scala中的val,var和lazy
转自:https://yerias.github.io/2020/03/19/scala/3/#3%EF%BC%9Alazy%E4%BF%AE%E9%A5%B0%E7%AC%A6%E5%8F%AF%E ...
- Scala中apply的用法
Scala中的 apply 方法有着不同的含义, 对于函数来说该方法意味着调用function本身, 以下说明摘自Programming in Scala, 3rd Edition Every fun ...
随机推荐
- vsftp 根据用户设置
#vsftpd.conf ###############pam_service_name=vsftpduserlist_enable=YEStcp_wrappers=YESlocal_root=/da ...
- 编译FFmpeg成一个SO库<转>
转帖地址:http://www.ihubin.com/blog/android-ffmpeg-demo-3/ ============================================= ...
- netstat命令
netstat命令会罗列出当前所有的网络连接.连接统计以及路由表信息.默认情况下,netstat命令将罗列出本地计算机所有开启的端口情况,以及它所连接的外部计算机情况. 端口就像一所房子的房门一样.数 ...
- 一些对数学领域及数学研究的个人看法(转载自博士论坛wcboy)
转自:http://www.math.org.cn/forum.php?mod=viewthread&tid=14819&extra=&page=1 原作者: wcboy 现在 ...
- nginx的优化
Nginx 优化 Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为"engine X",是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/P ...
- webForm中的验证控件
1.非空验证控件:RequireFieldValidator :2.数据比较验证:CompareValidator :3.数据范围验证:RangeValidator :4.正则表达式验证:Regul ...
- UNDO内存结构剖析
UNDO内存结构剖析 一.场景 Oracle的 C事物从早上9:00开始读取A表全部10w行数据,这个而读取需要经历5分钟.在9:01的时候,B事物将A表删除100条记录,那么,当9:05的时候,事物 ...
- Python 3.6.0的sqlite3模块无法执行VACUUM语句
Python 3.6.0的sqlite3模块存在一个bug(见issue 29003),无法执行VACUUM语句. 一执行就出现异常: Traceback (most recent call last ...
- MFC 使用位图按钮,并且设置按钮的鼠标悬停效果
系统环境:Windows 10软件环境:Visual C++ 2013 SP1本次目的:使用位图按钮,并且设置按钮的鼠标悬停效果 在用MFC开发时,界面是比较不好开发的一块.VC中自带了CBitmap ...
- 《IT蓝豹》PlayNewsStandDemo资讯类新闻客户端框架
PlayNewsStandDemo资讯类新闻客户端框架,支持tab滑动切换,当切换到最左边或者最后边的时候停止滑动 本例子切换tab的效果根据AccelerateDecelerateInterpola ...