2017-06-20 80 views
0

阿帕奇SparkContext ClassTag和AnyRef约束的泛型函数有一个方法:写在斯卡拉

def broadcast[T: ClassTag](value: T): Broadcast[T] 

我尝试写分析数据的包装(现在它只是试图登录大小)和调用原始的方法:

def broadcast[T: ClassTag](value: T): Broadcast[T] = { 
    val sizeEst = SizeEstimator.estimate(value) 
    log.debug(s"Broacasting $sizeEst bytes of data") 
    sc.broadcast(value) 
} 

org.apache.spark.util.SizeEstimator期待一个AnyRef,所以我得到一个错误。我对Scala并不是特别有经验,所以ClassTag -s对我来说有点神奇。

如何解决这个代码片段,这样既sc.broadcast(其中预计ClassTag)和SizeEstimator.estimate(其预计的AnyRef)都开心吗?

回答

2

您可以将T定义为扩展AnyRef的类型,此外还执行隐式ClassTag。请注意,这会限制你的boradcast版本的广播只有AnyRef子类,使用(基本上所有的非原语,见http://docs.scala-lang.org/tutorials/tour/unified-types.html):

def broadcast[T <: AnyRef : ClassTag](value: T): Broadcast[T] = { 
    val sizeEst = SizeEstimator.estimate(value) 
    log.debug(s"Broacasting $sizeEst bytes of data") 
    sc.broadcast(value) 
} 

broadcast(List(1,2,3)) // compiles 
broadcast("str")  // compiles 
broadcast(1)   // does not compile, because Int does not extend AnyRef 
+0

是的,我明白了从'AnyRef'继承所施加的限制。感谢您帮助我理解正确的语法。 –

2

作为替代Tzach琐的回答是:因为通用T无论如何都会被装箱,其实这是一个罕见的情况下asInstanceOf不存在任何问题:

def broadcast[T: ClassTag](value: T): Broadcast[T] = { 
    val sizeEst = SizeEstimator.estimate(value.asInstanceOf[AnyRef]) 
    log.debug(s"Broacasting $sizeEst bytes of data") 
    sc.broadcast(value) 
}