我注意到如果我申请 mapPartitions
在 RDD 上,分区获得一个可迭代对象。内mapPartitions
函数,然后我调用 toArray
可迭代对象的成员函数,用于将该可迭代对象转换为 Array 对象。是否调用toArray
涉及复制,还是只是开始引用与数组相同的内存部分?如果确实涉及复制,有什么方法可以防止复制?
最佳答案
对您的问题的一个重要更正 - 在 mapPartitions
期间公开的分区数据结构是一个迭代器,而不是可迭代的。接口(interface)区别如下:
Iterator
有 next()
和 hasNext()
方法,允许您访问集合中的每个元素一次。一旦调用了迭代器的 next()
方法,最后一个元素就消失了(除非您将它存储在变量中)。 Iterable
可以随时生成一个 Iterator
。这使您可以根据需要多次访问每个元素。 在实现方面,
Iterator
可以流式传输数据。您实际上一次只需要在内存中拥有一个元素,该元素在调用 next()
时加载。如果您正在使用 Spark ( sc.textFile
) 从文本文件中读取数据,它会执行此操作,并且几乎不使用内存来通过分区进行简单的迭代。您绝对可以调用
iterator.toArray
,但您可能不想这样做。您最终将所有数据插入内存(Spark 不能一次仅加载一个元素,因为您一次要求所有元素),然后复制每条数据(对于原语,例如 Int
) 或为每条数据分配一个新的引用(对于 AnyRef
,如 Array[_]
)。没有办法阻止这种复制。有时您想要将分区迭代器转换为数组,但这些用例很少见。由于不必要的分配和 GC,您可能会耗尽内存并大大降低应用程序的速度,因此请认真考虑是否真的需要它!
关于arrays - Spark中iterable与Array的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41264566/