Scala apachespark中的Case类相等
为什么Spark中的模式匹配与Scala中的工作方式不同?见下面的例子。。。函数Scala apachespark中的Case类相等,scala,apache-spark,pattern-matching,rdd,case-class,Scala,Apache Spark,Pattern Matching,Rdd,Case Class,为什么Spark中的模式匹配与Scala中的工作方式不同?见下面的例子。。。函数f()尝试在类上进行模式匹配,该类在Scala REPL中工作,但在Spark中失败,并导致所有“?”f2()是一种变通方法,它使用.isInstanceOf()在Spark中获得所需的结果,但我知道这在Scala中是不好的形式 在Spark中,任何关于模式匹配的正确方法的帮助都将不胜感激 abstract class a extends Serializable {val a: Int} case class b(
f()
尝试在类上进行模式匹配,该类在Scala REPL中工作,但在Spark中失败,并导致所有“?”f2()
是一种变通方法,它使用.isInstanceOf()
在Spark中获得所需的结果,但我知道这在Scala中是不好的形式
在Spark中,任何关于模式匹配的正确方法的帮助都将不胜感激
abstract class a extends Serializable {val a: Int}
case class b(a: Int) extends a
case class bNull(a: Int=0) extends a
val x: List[a] = List(b(0), b(1), bNull())
val xRdd = sc.parallelize(x)
尝试在Scala REPL中工作但在Spark中失败的模式匹配
def f(x: a) = x match {
case b(n) => "b"
case bNull(n) => "bnull"
case _ => "???"
}
在Spark中运行的变通方法,但形式不好(我认为)
查看结果
xRdd.map(f).collect //does not work in Spark
// result: Array("???", "???", "???")
xRdd.map(f2).collect // works in Spark
// resut: Array("b", "b", "bnull")
x.map(f(_)) // works in Scala REPL
// result: List("b", "b", "bnull")
使用的版本。。。
火花结果在火花壳中运行(AWS EMR-4.3上的火花1.6)
SBT 0.13.9(Scala 2.10.5)中的Scala REPL这是Spark REPL的一个已知问题。您可以在中找到更多详细信息。它影响Spark REPL中的多个操作,包括
成对DDS
上的大多数转换。例如:
case class Foo(x: Int)
val foos = Seq(Foo(1), Foo(1), Foo(2), Foo(2))
foos.distinct.size
// Int = 2
val foosRdd = sc.parallelize(foos, 4)
foosRdd.distinct.count
// Long = 4
foosRdd.map((_, 1)).reduceByKey(_ + _).collect
// Array[(Foo, Int)] = Array((Foo(1),1), (Foo(1),1), (Foo(2),1), (Foo(2),1))
foosRdd.first == foos.head
// Boolean = false
Foo.unapply(foosRdd.first) == Foo.unapply(foos.head)
// Boolean = true
更糟糕的是,结果取决于数据分布:
sc.parallelize(foos, 1).distinct.count
// Long = 2
sc.parallelize(foos, 1).map((_, 1)).reduceByKey(_ + _).collect
// Array[(Foo, Int)] = Array((Foo(2),2), (Foo(1),2))
您可以做的最简单的事情是在REPL外部定义和打包所需的case类。使用spark submit
直接提交的任何代码也应该有效
在Scala 2.11+中,您可以使用粘贴-raw
直接在REPL中创建包
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package bar
case class Bar(x: Int)
// Exiting paste mode, now interpreting.
scala> import bar.Bar
import bar.Bar
scala> sc.parallelize(Seq(Bar(1), Bar(1), Bar(2), Bar(2))).distinct.collect
res1: Array[bar.Bar] = Array(Bar(1), Bar(2))
这是Spark REPL的已知问题。您可以在中找到更多详细信息。它影响Spark REPL中的多个操作,包括
成对DDS
上的大多数转换。例如:
case class Foo(x: Int)
val foos = Seq(Foo(1), Foo(1), Foo(2), Foo(2))
foos.distinct.size
// Int = 2
val foosRdd = sc.parallelize(foos, 4)
foosRdd.distinct.count
// Long = 4
foosRdd.map((_, 1)).reduceByKey(_ + _).collect
// Array[(Foo, Int)] = Array((Foo(1),1), (Foo(1),1), (Foo(2),1), (Foo(2),1))
foosRdd.first == foos.head
// Boolean = false
Foo.unapply(foosRdd.first) == Foo.unapply(foos.head)
// Boolean = true
更糟糕的是,结果取决于数据分布:
sc.parallelize(foos, 1).distinct.count
// Long = 2
sc.parallelize(foos, 1).map((_, 1)).reduceByKey(_ + _).collect
// Array[(Foo, Int)] = Array((Foo(2),2), (Foo(1),2))
您可以做的最简单的事情是在REPL外部定义和打包所需的case类。使用spark submit
直接提交的任何代码也应该有效
在Scala 2.11+中,您可以使用粘贴-raw
直接在REPL中创建包
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package bar
case class Bar(x: Int)
// Exiting paste mode, now interpreting.
scala> import bar.Bar
import bar.Bar
scala> sc.parallelize(Seq(Bar(1), Bar(1), Bar(2), Bar(2))).distinct.collect
res1: Array[bar.Bar] = Array(Bar(1), Bar(2))
谢谢你!我看到有人提到模式匹配在火花壳中不起作用,但没有细节。。。你是说如果我在jar中定义我的案例类,我就能在REPL中对它们进行模式匹配?再次感谢!确切地定义外部,构建jar,包括在
类路径中
并导入。感谢zero323!我看到有人提到模式匹配在火花壳中不起作用,但没有细节。。。你是说如果我在jar中定义我的案例类,我就能在REPL中对它们进行模式匹配?再次感谢!确切地在外部定义、构建jar、包含在类路径中并导入。