ParSet的zipWithIndex出现意外行为

时间:2013-09-09 06:00:07

标签: scala

我发现Scala 2.9.2 ParSet zipWithIndex有一些有趣的行为,我想知道这是一个bug还是一个功能。如果答案很明显,我很抱歉,因为我是Scala初学者。

以下是展示此问题的会话。

Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val x = Array(1,2,3,4,5,6,7,8)
x: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

// expected behavior

scala> x.toSet
res6: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 8, 4)

scala> x.toSet.zipWithIndex
res2: scala.collection.immutable.Set[(Int, Int)] = Set((1,1), (3,5), (4,7), (5,0), (6,2), (2,3), (8,6), (7,4))

// so far so good. let's try parallel implementation

scala> x.par.toSet
res0: scala.collection.parallel.immutable.ParSet[Int] = ParSet(5, 1, 6, 2, 7, 3, 8, 4)

// 
// 
// UNEXPECTED BEHAVIOR HERE
// 
scala> x.par.toSet.zipWithIndex
res1: scala.collection.parallel.immutable.ParSet[(Int, Int)] = ParSet((5,7), (6,5), (2,4), (1,6), (3,2), (4,0), (7,3), (8,1))

// just for good measure, this isn't an issue with Array or ParArray:
scala> x.zipWithIndex
res3: Array[(Int, Int)] = Array((1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6), (8,7))

scala> x.par.zipWithIndex
res7: scala.collection.parallel.mutable.ParArray[(Int, Int)] = ParArray((1,0), (2,1), (3,2), (4,3), (5,4), (6,5), (7,6), (8,7))

这是预期的行为吗?为什么ParSet的行为不等于Set?

1 个答案:

答案 0 :(得分:0)

  1. 通过定义集合 - 元素的顺序是意外的 - 特定于实现的顺序。当你zipWithIndex时,你实际上在不同的实现中揭示了不同的顺序。

    如果您采用其他Set实施,您将获得另一个订单,并相应地获得另一组(orderPos, element)

  2. 意外行为的另一个来源是zipWithIndex的非关联性: http://docs.scala-lang.org/overviews/parallel-collections/overview.html#nonassociative_operations

    我认为,如果您多次运行x.par.toSet.zipWithIndex,您可能会不时获得不同的结果(可能是为了更长时间的收集)。

    <强>更新

    我已经运行了几次:

    scala>  x.par.toSet.zipWithIndex
    res0: scala.collection.parallel.immutable.ParSet[(Int, Int)] = 
     ParSet((4,0), (8,1), (1,6), (6,5), (7,3), (5,7), (3,2), (2,4))
    
    scala>  x.par.toSet.zipWithIndex
    res1: scala.collection.parallel.immutable.ParSet[(Int, Int)] = 
     ParSet((4,0), (8,1), (6,5), (2,4), (3,3), (1,7), (7,2), (5,6))
    

    结果不同。