这两种功能格式之间的区别

时间:2015-08-14 16:21:57

标签: scala apache-spark

我正在研究spark而不是scala专家。我有两个地图功能的变种。你能解释一下它们之间的区别吗?

第一种变体和已知格式。

第一个变种

val.map( (x,y) => x.size()) 

第二个变体 - >这已经应用于元组

val.map({case (x, y) => y.toString()});

val的类型是RDD[(IntWritable, Text)]。当我尝试使用第一个函数时,它给出了如下错误。

  

类型不匹配;   发现:(org.apache.hadoop.io.IntWritable,org.apache.hadoop.io.Text)⇒单位   必需:((org.apache.hadoop.io.IntWritable,org.apache.hadoop.io.Text))⇒单位

当我添加额外的括号时,它说,

  

无法在方法或函数参数中直接对元组进行解构。

3 个答案:

答案 0 :(得分:3)

嗯,你说:

  

val的类型是RDD [(IntWritable,Text)]

所以它是一个以IntWritableText为组成部分的arity 2元组。

如果你说

val.map( (x,y) => x.size())

你正在做的是你实际上传递了一个Function2,一个带有两个参数的函数到map函数。这将永远不会编译,因为map想要一个带有一个参数的函数。你能做的是以下几点:

val.map((xy: (IntWritable, Text)) => xy._2.toString)

使用._2获取以xy传入的元组的第二部分(类型注释不是必需的,但会更清晰)。

现在是第二个变种(你可以省略外围的那些):

val.map { case (x, y) => y.toString() }

这是一种特殊的scala语法,用于创建一个PartialFunction语法,该语法在传入以访问xy部分的元组上立即匹配。这是可能的,因为PartialFunction从常规Function1类(Function1[A,B]可以写成A => B)扩展为一个参数。

希望更清楚:)

答案 1 :(得分:0)

我在repl中尝试这个:

scala> val l = List(("firstname", "tom"), ("secondname", "kate"))
l: List[(String, String)] = List((firstname,tom), (secondname,kate))

scala> l.map((x, y) => x.size)
<console>:9: error: missing parameter type
Note: The expected type requires a one-argument function accepting a    2-Tuple.
  Consider a pattern matching anonymous function, `{ case (x, y) =>  ... }`
          l.map((x, y) => x.size)

也许可以给你一些启发。

答案 2 :(得分:0)

你的第一个例子是一个带有两个参数并返回一个String的函数。这与此示例类似:

scala> val f = (x:Int,y:Int) => x + y
f: (Int, Int) => Int = <function2>

你可以看到f的类型是(Int,Int) => Int(只是略微改变了这个以返回int而不是字符串)。这意味着这是一个函数,它接受两个Int作为参数并返回一个Int作为结果。

现在你拥有的第二个例子是用于编写这样的东西的语法糖(快捷方式):

scala> val g = (k: (Int, Int)) => k match { case (x: Int, y: Int) => x + y }
g: ((Int, Int)) => Int = <function1>

您看到函数g的返回类型现在是((Int, Int)) => Int。您看得出来差别吗?输入类型g有两个括号。这表明g接受一个参数,该参数必须是Tuple[Int,Int](或简称为(Int,Int))。

回到你的RDD,你拥有的是Tuple[IntWritable, Text]的集合,所以第二个功能将起作用,而第一个功能将不起作用。