哪种方法引发连接取决于完成连接

时间:2015-04-30 02:19:33

标签: apache-spark

我想编写自己的JavaPairRDD Key类并实现自己的连接逻辑。所以我需要重写密钥类的equals()和hashCode()方法,或者重写其他方法。 例如: 您知道JavaPairRDD.join(JavaPairRDD)非常简单,就在StringKey1.equals(StringKey2)匹配时。 但对我来说,我希望即使key1只是key2的子串也匹配。因此,我认为我必须编写一个包装类来告诉Spark,只要它们与我的逻辑匹配就应该将它们视为同一个键,并加入它们。例如,“ab”应与“abc”连接。

2 个答案:

答案 0 :(得分:1)

您需要覆盖equalshashCode。但是,您需要尝试显式转换other对象,因为模式匹配不起作用。我仍在试图弄清楚为什么匹配单独失败(我猜测序列化)。还要记住,如果关键对象真的不匹配,那么在最终输出中会覆盖另一个...这可能不是你想要的。

case class Foo(x: String) {
  override def equals(other: Any) = { 
    Option(other).map(_.asInstanceOf[Foo]).getOrElse(null)
    match 
    {
      case f : Foo => 
        x contains(f.x)
      case _ => false
    }
  }

  override def hashCode() = 1
}

sc.parallelize(List((Foo("abcdefg"),1))).join(sc.parallelize(List((Foo("abcdef"),1)))).collect

答案 1 :(得分:1)

攻击equalshashCode的语义以强制火花加入不相等的东西是一个坏主意。

Spark依赖于密钥的hashCode来对集群上的数据进行分区。强制一个常量hashCode将强制数据转到单个分区,从而消除了在集群上分配计算的可能性。这意味着计算可以/应该在一个节点中完成,可能使用适当的单节点技术。

使用Spark可以解决此问题,采用不同的方法:

val data1 = List("abcd" -> 4, "defghy" -> 6 , "wxxyyy" -> 3, "az" -> 24)
val data2 = List("ab" -> 2, "fghz" -> 3 , "y" -> 1, "a" -> 2)

val base = sparkContext.parallelize(data1)
val jn = sparkContext.parallelize(data2)

val cartesian = base.cartesian(jn)

val joined = cartesian.collect{case ((k1,v1),(k2,v2)) if (k1.contains(k2)) => (k1,(v1,v2))}

joined.collect

这导致:

res6: Array[(String, (Int, Int))] = Array((abcd,(4,2)), (defghy,(6,1)), (wxxyyy,(3,1)), (az,(24,2)))