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放在同一个迭代体中,执行结果会和在两个迭代体中执行结果一致。但是执行结果却是能够正常的统计出数量,证明了推测原因2不成立。

  对原因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没有相似的方法;

时间: 2024-08-01 02:18:15

Scala中Iterator允许执行一次的相关文章

Crontab中shell每分钟执行一次HDFS文件上传不执行的解决方案

一.Crontab -e 加入输出Log */1 * * * * /qiwen_list/upload_to_hdfs.sh > /qiwen_list/mapred.log 2>&1 二.查看Log发现,找不到Hadoop 三.脚本中指定Hadoop完整路径 #!/bin/sh#upload list to hdfs yesterday=`date --date='1 day ago' +%Y%m%d` echo $yesterday/home/hadoop/bin/hadoop f

Scala中的集合:Iterator、BitSet、Set、Map、Stack、Vector、List、Array

 5.   util包 5.1.     架构 http://www.scala-lang.org/docu/files/collections-api/collections.html The following figure shows all collections in package scala.collection. These are all high-level abstract classes or traits, which generally have mutable

selenium+python+unittest:一个类中只执行一次setUpClass和tearDownClass里面的内容(可解决重复打开浏览器和关闭浏览器,或重复登录等问题)

unittest框架是python自带的,所以直接import unittest即可,定义测试类时,父类是unittest.TestCase. 可实现执行测试前置条件.测试后置条件,对比预期结果和实际结果,检查程序的状态,生成测试报告. 且断言的话unittest框架很方便. 在这主要记录下setUp()和tearDown()这两个的问题,每次执行一个测试用例(test开头的方法),就会执行一次setUp()和tearDown(), 导致执行多个测试用例时,会反复的打开浏览器操作,这个很浪费时间

Scala中apply的用法

Scala中的 apply 方法有着不同的含义, 对于函数来说该方法意味着调用function本身, 以下说明摘自Programming in Scala, 3rd Edition Every function value is an instance of some class that extends one of several FunctionN traits in package scala, such as Function0 for functions with no parame

JQuery事件绑定函数one:绑定的事件处理函数只会被执行一次

JQuery绑定事件处理函数,有两种方式(方式1和方式2)是最常用的,方式3使用的较少. 方式1: $("#button").click(function(){ }); 这种方式很简单,也是平时编码最常用的做法.HTML中原始的事件,如onclick.onmouseover.onkeypress等,JQuery对名称进行了简单的封装,如onclick与JQuery的click对应,onmouseover与JQuery的mouseover对应.查看JQuery的API可以发现:JQuer

执行一条sql语句update多条记录实现思路

执行一条sql语句update多条记录实现思路 如果你想更新多行数据,并且每行记录的各字段值都是各不一样,你会怎么办呢?本文以一个示例向大家讲解下如何实现如标题所示的情况,有此需求的朋友可以了解下 通常情况下,我们会使用以下SQL语句来更新字段值: UPDATE mytable SET myfield='value' WHERE other_field='other_value'; 但是,如果你想更新多行数据,并且每行记录的各字段值都是各不一样,你会怎么办呢?举个例子,我的博客有三个分类目录(免

MFC长按键盘:执行多次、执行一次

先说明一下你按下一个键盘不松开的时候发生了什么:产生了多个按下的消息,切消息的内容都一样,是你按下的那个键. 实现长按的时候执行多次:比如你长按"A"按钮,可以让界面上的某个控件的数值一直增大,那么你只要在实现这个按键的响应事件里增大一次就可以了,只要你长按,自动会多次调用你的这个函数. 实现长按的时候执行一次:这个按照网上的说法,可以添加一个静态变量,记录上次按了哪个键.主要的代码如下 (1)给类添加一个静态变量 private: static WPARAM last_key; (2

MFC键盘长按执行多次与执行一次

先说明一下你按下一个键盘不松开的时候发生了什么:产生了多个按下的消息,切消息的内容都一样,是你按下的那个键. 实现长按的时候执行多次:比如你长按"A"按钮,可以让界面上的某个控件的数值一直增大,那么你只要在实现这个按键的响应事件里增大一次就可以了,只要你长按,自动会多次调用你的这个函数. 实现长按的时候执行一次:这个按照网上的说法,可以添加一个静态变量,记录上次按了哪个键.主要的代码如下 (1)给类添加一个静态变量 private: static WPARAM last_key; (2

畅销书对Java中Iterator的理解误区

声明:本博客为原创博客,未经允许,不得转载!原文链接为http://blog.csdn.net/bettarwang/article/details/28110615 最近放假,闲来无事,便翻看以前看过的一些书,竟然发现有些书本(甚至是一些畅销书)对Java中Iterator有很大的误解,比如某畅销书在Collection那一章有这么一句话:"当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对集