您的位置:首页 > 其它

rdd,scala中的占位符“_”

2017-03-24 01:49 211 查看
1、通配符。类似Java中的*。如:
import scala.math._


2、作为一个整体。
:_*
,告诉编译器你希望将某个参数当作参数序列处理!例如
val s = sum(1 to 5:_*)
就是将1 to 5当作参数序列处理。

3、指代一个集合中的每个元素。例如我们要在一个Array a中筛出偶数,并乘以2,可以用以下办法:
a.filter(_%2==0).map(2*_)


4、在元组中访问组员。如:
("scala","spark")._2


5、某一类型的默认值。如:

var a : Int = _  //a=0
var a : Double = _ //a=0.0
var a : Person = _ //a=null


补充说明:

对于方法中函数作为的占位符,看函数形参决定,例如:

val conf = new SparkConf().setAppName("helloworld").setMaster("local[2]")
val sc = new SparkContext(conf)
val rdd = sc.parallelize(List(("hello", 1), ("hello", 2), ("scala", 1), ("hello", 1), ("world", 1), ("world", 1)))
val rdd1 = rdd.groupBy(_._1)

//原来的用法
//    val rdd2 = rdd1.mapValues(_.foldLeft(0)((a: Int, b: (String, Int)) => a + b._2))
//使用占位符的用法
val rdd2 = rdd1.mapValues(_.foldLeft(0)(_+_._2))
//    rdd1.mapValues(_.foldLeft(0)(_._2+_)) //错误
//    rdd1.mapValues(_.foldLeft(0)(_)) //错误


groupBy方法源码:

abstract class RDD[T: ClassTag](
@transient private var _sc: SparkContext,
@transient private var deps: Seq[Dependency[_]]
) extends Serializable with Logging {
...

def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])] = withScope {
groupBy[K](f, defaultPartitioner(this))
}

...
}


由于 f 是单形参:输入参数类型是(String, Int),此时
val rdd1 = rdd.groupBy(_._1)
中的_代表当前(String, Int),输出类型K由
_._1
确定,即 Int

foldLeft方法源码:

trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
...
def foldLeft[B](z: B)(op: (B, A) => B): B = {
var result = z
this.seq foreach (x => result = op(result, x))
result
}
...
}


op: (B, A) => B中,B已由初始值决定是Int类型,A代表元素本身类型(String, Int)

foldLeft(0)(_+_._2)
中,”+”左边的”
_
“代表当前值op(result, x)中的result,他的类型是Int(B确定)。”+” 右边第一个”
_
“代表当前元素x(A确定),即(String, Int)类型,所以,要返回Int类型结果,必须取”
_._2
“。

不能这样用:

rdd1.mapValues(_.foldLeft(0)(_._2+_)) //错误
rdd1.mapValues(_.foldLeft(0)(_)) //错误
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: