Spark:reduceByKey 的自定义键比较方法

4
我需要在Scala中使用自己的类作为键/值对中的键。具体来说,我有一个简单的类,它保存两个变量"id1"和"id2",我希望元素仅基于"id2"而不是"id1"进行分组。我无法在网上找到任何关于如何覆盖"reduceByKey()"方法的比较方法以便根据我的自定义"compare()"方法分组具有相同键的元素的信息。
欢迎提供任何帮助。 谢谢。
3个回答

3
你不能覆盖reduceByKey的比较方法,因为它将无法利用数据通常在集群中的不同执行器上按键进行分组的事实。但你可以更改键(并注意根据你使用的转换/操作,这很可能会重新分组数据)。RDD中有一个巧妙的方法可以做到这一点,叫做keyBy,所以你可以像这样做:
val data: RDD[MyClass] = ...    // Same code you have now.
val byId2 = data.keyBy(_.id2)   //Assuming your ids are Longs, will produce a RDD[(Long,MyClass)]

这将完全按照您的要求执行,无需进行任何其他更改。 - Dean Wampler

2
如果您能够更改您的类,那么reduceByKey会使用equalshashCode。因此,您可以确保这些方法被定义,并且这将导致正确的比较被使用。

是的,我能够做到。谢谢,我会尝试继续处理这个问题。 - Sasha
不要忘记点赞并标记为答案,如果它对您有用 :) - Justin Pihony
我遇到了其他问题,需要先解决它们,然后再回来处理这个问题! - Sasha

0

你不能只是map一下RDD,让键值对的第一个元素成为你想要使用的键吗?

case class MyClass(id1: Int, id2: Int)
val rddToReduce: Rdd[(MyClass, String)] = ... //An RDD with MyClass as key

rddToReduce.map {
  case (MyClass(id1, id2), value) => (id2, (id1, value)) //now the key is id2
} .reduceByKey {
  case (id1, value) => //do the combination here
  ...
} .map {
  case (id2, (id1, combinedValue)) =>
  (MyClass(id1, id2), combinedValue) //rearrange so that MyClass is the key again
}

有些事情我应该提一下 - 在映射之后,我需要键保持为包含id1和id2的自定义对象,因为尽管我需要按id2分组,但我需要id1保持不变,因为稍后我会根据id1重新映射和重新分组值。我认为你建议的方法会放弃id1? - Sasha
我已经更新了示例,通过传递 id1。但是你必须放弃一些 id1 - 考虑一下如果你有两个具有相同 id2 但不同 id1 的条目会发生什么?你只能得到一个元素(因为它们具有相同的 id2 被合并),所以你只能得到一个 id1 - lmm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接