如何让Scala并行集合保持插入顺序?
如何在Scala并行集合处理后保留插入顺序?
这个问题太常见了!并行集合因为多线程并行处理的特性,默认的foreach会在元素处理完成后立即输出,所以顺序看起来是随机的,但其实我们有两种简单的办法来保留原始的插入顺序:
方法一:使用foreachOrdered方法
Scala的并行集合专门提供了foreachOrdered方法,它会严格按照原始集合的元素顺序来执行传入的操作——哪怕元素的处理是并行完成的,输出的时候也会等待前面的元素处理完毕后再输出后面的,完美匹配你的需求。
修改后的代码如下:
object Test { def main(args: Array[String]): Unit = { val vec = Vector(1,2,3,4,5,6) val x = vec.map(myFunc(_)) x.foreach{println} val par = vec.par val parx = par.map(myFunc(_)) // 替换foreach为foreachOrdered parx.foreachOrdered{println} } def myFunc(a:Int) : Int = { return a*a } }
方法二:转换为串行集合后再遍历
并行有序集合(比如ParVector、ParList)本身是维护了元素的原始顺序的,只是默认的foreach是并行执行的。你可以先把并行集合转换回串行集合(比如Vector、List),之后用串行集合的foreach遍历,自然就会按原始顺序输出了。
示例代码:
object Test { def main(args: Array[String]): Unit = { val vec = Vector(1,2,3,4,5,6) val x = vec.map(myFunc(_)) x.foreach{println} val par = vec.par val parx = par.map(myFunc(_)) // 转换为串行Vector后遍历 parx.toVector.foreach{println} // 如果是List的话,用parx.toList.foreach{println}即可 } def myFunc(a:Int) : Int = { return a*a } }
这两种方法对Vector、List等所有有序集合转成的并行集合都适用,你可以根据自己的场景选择:如果只是需要遍历输出有序,用foreachOrdered更高效;如果需要后续对结果集合进行串行操作,转成串行集合会更方便。
内容的提问来源于stack exchange,提问作者Rahul Raj
相关产品推荐
相关产品推荐

