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 ...
随机推荐
- 施耐德Sepam 40系列备自投逻辑
1# 主供: VL1= NOT PVTS_1_3 V1 = VL1 AND P59_1_7 AND P59_1_8 AND P59_1_9VL2 = VL1 AND I12 AND I21 AND I ...
- Thinkphp的单字母函数整理
有人不太喜欢TP这种单字母函数,其实这也是TP的一个特色,如果理解了这些函数的作用,不管是背,还是写,都是非常方便的,接下来我们以字母顺序开始.A函数 B函数 C函数 D函数 F函数 L函数 R函数 ...
- Xmodem Bootloader
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 多年前玩Cisco交换 ...
- js中array的filter用法
function bouncer(arr) { // Don't show a false ID to this bouncer. arr = arr.filter(function(val) { i ...
- sellsa
我看见天空很蓝 就像你在我身边的温暖 生命有太多遗憾 人越成长越觉得孤单 我很想飞 多远都不会累 才明白爱得越深心就会越痛 我只想飞 在我的天空飞 我知道你会在我身边 回忆的画面 记录的语言 爱始终是 ...
- IS A 和 HAS A的区别
IS A:一般是用作继承或者接口类.比如:中国人和外国人都是人,重点在:是一个... . HAS A:一般用作对象和他的成员的从属关系.比如:中国人和外国人都有眼睛.耳朵.嘴巴.重点在:有一个... ...
- PHP连接MySQL的时候报错SQLSTATE[HY000] [2002] No such file or directory
错误环境:Mac OS 10.10 找到mysql.sock文件的位置 $sudo find / -name mysql.sock ------结果如下---------- find: /dev/fd ...
- Ajax的封装03
一.Ajax 1.原理:基于http协议的 内置对象:XMLHttpRequest 发起请求 那会相应 步骤: var xhr=new XMLHttpRequest(); // 请 ...
- 深入理解js——作用域
"javaScript没有块级作用域",所谓"块",就是{}中间的内容.所以在声明变量的时候不要在"块"里面,要在一开始声明就好了. 其实j ...
- frame busting
[frame busting] 参考:http://book.51cto.com/art/201204/330076.htm