为什么Spark不允许映射端与数组键合并?

Vit*_*men 7 scala mapreduce apache-spark rdd

我正在使用Spark 1.3.1,我很好奇为什么Spark不允许在地图侧组合上使用数组键.一块combineByKey function:

if (keyClass.isArray) {
  if (mapSideCombine) {
    throw new SparkException("Cannot use map-side combining with array keys.")
  }
}
Run Code Online (Sandbox Code Playgroud)

zer*_*323 10

基本上出于同样的原因,默认分区程序无法对数组键进行分区.

Scala Array只是Java数组的包装器,它hashCode不依赖于内容:

scala> val x = Array(1, 2, 3)
x: Array[Int] = Array(1, 2, 3)

scala> val h = x.hashCode
h: Int = 630226932

scala> x(0) = -1

scala> x.hashCode() == h1
res3: Boolean = true
Run Code Online (Sandbox Code Playgroud)

这意味着具有完全相同内容的两个数组不相等

scala> x
res4: Array[Int] = Array(-1, 2, 3)

scala> val y = Array(-1, 2, 3)
y: Array[Int] = Array(-1, 2, 3)

scala> y == x
res5: Boolean = false
Run Code Online (Sandbox Code Playgroud)

结果Arrays不能用作有意义的键.如果您不相信只是检查当您使用ArrayScala的密钥时会发生什么Map:

scala> Map(Array(1) -> 1, Array(1) -> 2)
res7: scala.collection.immutable.Map[Array[Int],Int] = Map(Array(1) -> 1, Array(1) -> 2)
Run Code Online (Sandbox Code Playgroud)

如果要将集合用作键,则应使用不可变数据结构,如a Vector或a List.

scala> Map(Array(1).toVector -> 1, Array(1).toVector -> 2)
res15: scala.collection.immutable.Map[Vector[Int],Int] = Map(Vector(1) -> 2)
Run Code Online (Sandbox Code Playgroud)

也可以看看: