这个操作返回两个RDD的笛卡尔集.如果两个RDD中某一个RDD的结果集为空集时,这个结果集也是一个空集.
这个操作不会执行shuffle的操作.
def cartesian[U: ClassTag](other: RDD[U]): RDD[(T, U)] = withScope {
new CartesianRDD(sc, this, other)
}
从上面的代码中,可以看出,直接生成了一个CartesianRDD的实例.
这个实例的关键部分:
override def getPartitions: Array[Partition] = {
这个CartesianRDD的Partition的个数是要做笛卡尔集的上层两个RDD的partition的个数的乘积.
// create the cross product split
val array = new Array[Partition](rdd1.partitions.length * rdd2.partitions.length)
for (s1 <- rdd1.partitions; s2 <- rdd2.partitions) {
val idx = s1.index * numPartitionsInRdd2 + s2.index
array(idx) = new CartesianPartition(idx, rdd1, rdd2, s1.index, s2.index)
}
array
}
这里,按第一个RDD的结果集为基准结果集,对两个RDD中各partition的结果进行组合.类似于join.但不通过key进行组合,而是通过partition进行组合.下面代码的for是两层迭代.也就是说rdd1中每个partition的结果集中,都包含有rdd2中所有的partition的结果集.
override def compute(split: Partition, context: TaskContext): Iterator[(T, U)] = {
val currSplit = split.asInstanceOf[CartesianPartition]
for (x <- rdd1.iterator(currSplit.s1, context);
y <- rdd2.iterator(currSplit.s2, context)) yield (x, y)
}