我正在使用HashPartioner
但收到意外结果。
我使用3个不同的String作为键,并将partition参数设置为3,因此我希望有3个分区。
val cars = Array("Honda", "Toyota", "Kia")
val carnamePrice = sc.parallelize(for {
x <- cars
y <- Array(100,200,300)
} yield (x, y), 8)
val rddEachCar = carnamePrice.partitionBy(new HashPartitioner(3))
val mapped = rddEachCar.mapPartitionsWithIndex{
(index, iterator) => {
println("Called in Partition -> " + index)
val myList = iterator.toList
myList.map(x => x + " -> " + index).iterator
}
}
mapped.take(10)
结果如下。它只提供2个分区。我检查了String的哈希码 (69909220 75427 -1783892706)。这可能有什么问题?可能我误解了分区算法。
Array[String] = Array((Toyota,100) -> 0, (Toyota,200) -> 0, (Toyota,300) -> 0, (Honda,100) -> 1, (Honda,200) -> 1, (Honda,300) -> 1, (Kia,100) -> 1, (Kia,200) -> 1, (Kia,300) -> 1)
答案 0 :(得分:2)
这里没有什么奇怪的事。 HashPartitioner
使用的Utils.nonNegativeMod
按如下方式实施:
def nonNegativeMod(x: Int, mod: Int): Int = {
val rawMod = x % mod
rawMod + (if (rawMod < 0) mod else 0)
}
使用3个分区,密钥分配定义如下:
for { car <- Seq("Honda", "Toyota", "Kia") }
yield (car -> nonNegativeMod(car.hashCode, 3))
Seq[(String, Int)] = List((Honda,1), (Toyota,0), (Kia,1))
这正是你所得到的。换句话说,缺少直接哈希冲突并不能保证缺少冲突模数为任意数。