分享

spark开发基础之从Scala符号入门Scala

pig2 发表于 2016-11-6 19:31:45 [显示全部楼层] 只看大图 回帖奖励 阅读模式 关闭右栏 21 28855
本帖最后由 pig2 于 2016-11-24 09:46 编辑
问题导读

1.Scala中有哪些常见符号?
2.本文讲了哪些符号?
3.你对符号的理解是什么?
4.<-,->,=>,Int=,_ 它们含义是什么?用在什么地方?






当我们学习spark的时候,我们知道spark是使用Scala语言开发的,由于语言是相通的,所以对于传统程序员【Java,.net,c等】,我们能看懂Scala程序是没有问题的。但是当我们看到它的时候,却傻眼了。那么多符号,左箭头,右箭头,下划线等等搞得摸不着头脑。

看来如果想顺利的学习,我们必须学一下Scala了。很多都是从变量定义,函数,类等入门。由于我们可能有些其他语言基础,这里我们从Scala符号入门。一文能帮助大家阅读比较常见的Scala程序。


Scala符号
如果你学过其它语言,特别是.net语言,那么你能看懂Java语言。无论是C,C++,还是其它语言,它们的变量,函数的定义都是差不多的。你能知道这是一个函数,并且大概懂得它实现了什么。但是如果你阅读过Scala代码,你会感觉摸不着头脑。里面有各种奇葩符号,比如:<-,->,=>,Int=,_ ,甚至还有空格。同样还有没有见过的关键字,with,apply。

我们来看看这些符号都用在什么地方:
第一个
:这个符号<-用在什么地方,比如用于for循环,
<-用于遍历集合对象(可遍历对象)B,在每次遍历的过程中,生成一个新的对象A,这个A是val,而不是var,然后对循环体中对A进行处理,<-在Scala中称为generator。 不需要显式的指定A的类型,因为Scala使用自动推导的方式根据B的元素类型得出A的类型
示例1:
[mw_shl_code=bash,true]for (arg <- args)  
println(arg) [/mw_shl_code]
上面是什么含义?
循环args,打印出里面的元素

示例2:
[mw_shl_code=bash,true]for (i <- 0 to 2)  
print(greetStrings(i))  [/mw_shl_code]
上面的含义是遍历一个数组
[mw_shl_code=bash,true]val A= new Array[String](3)  

A(0) = "Hello"
A(1) = ", "
A(2) = "world!\n"

for (i <- 0 to 2)  
print(A(i))  [/mw_shl_code]

这个符号其实很碍眼,导致你可能根本弄不清楚为什么要搞这么个符号。而且很可能被我们误认为是一个负号。这样就增大了我们的阅读难度。但是如何你习惯了,其实Scala还是不错的,间接而且思想跟别的语言有很大的区别。
这里出现的英文to,也是比较奇怪的,我们看到过变量和函数使用英文,但是在for语句中使用英文,这也太随意了,不知道的以为是在做阅读理解。其实这里的to,是0的一个方法,全写
[mw_shl_code=scala,true]for (i <- 0.to(2))    [/mw_shl_code]

第二个符号->
->方法是所有Scala对象都有的方法,比如A->B,->方法调用的结果是返回一个二元的元组(A,B)
这个符号用于什么地方,比如map映射
Map(映射)是一种可迭代的键值对(key/value)结构。
// Map 键值对演示
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
上面是定义map,那么map该如何操作:
Scala Map 有三个基本操作:
方法描述
keys返回 Map 所有的键(key)
values返回 Map 所有的值(value)
isEmpty在 Map 为空时返回true


实例
以下实例演示了以上三个方法的基本应用:
[mw_shl_code=bash,true]object Test {
   def main(args: Array[String]) {
      val colors = Map("red" -> "#FF0000",
                       "azure" -> "#F0FFFF",
                       "peru" -> "#CD853F")

      val nums: Map[Int, Int] = Map()

      println( "colors 中的键为 : " + colors.keys )
      println( "colors 中的值为 : " + colors.values )
      println( "检测 colors 是否为空 : " + colors.isEmpty )
      println( "检测 nums 是否为空 : " + nums.isEmpty )
   }
}[/mw_shl_code]
执行以上代码,输出结果为:
[mw_shl_code=bash,true]$ scalac Test.scala
$ scala Test
colors 中的键为 : Set(red, azure, peru)
colors 中的值为 : MapLike(#FF0000, #F0FFFF, #CD853F)
检测 colors 是否为空 : false
检测 nums 是否为空 : true[/mw_shl_code]

map映射与map函数的区别
同时有一个小小的不同:
如果刚接触map函数会让我们特别的困惑和难懂。
~~~~~~~~~~~~~~~~~~~~~~~~~~~


map函数:

函数式编程都有一个map函数,map函数就像一个加工厂,传入一个函数,利用这个函数将集合里的每一个元素处理并将结果返回。

aList.map(processFunc)//就这么简单,aList中的每一个元素将会变成processFunc的返回值。 这个processFunc一般都是匿名函数,因为用过一次后就用不到了。

[mw_shl_code=bash,true]val l = List(1,2,3)
var ll = l.map(x => x*x)//返回 ll=(1,4,9)[/mw_shl_code]



~~~~~~~~~~~~~~~~~~~~~~~~~~~

第三个符号=>
这些符号说大于不是大于,说等号不是等号。它代表什么意思.我们来看下面内容:
1142010.jpg
这个咋看到不明所以,左边像参数传递,右箭头右侧像一个加法运算。而这个其实是Scala的匿名函数。
左边是参数,右边是函数体。在我们印象中,函数体一般都是在大括号中,而这里真让我们难以理解。
总之:方法参数=> 方法体这时候我们需要明白这是匿名函数
这就是Scala不走寻常路,而且其它的很多地方,都是这个样子。比如下面的函数定义等等。这里先给大家认识下Scala的匿名函数

[mw_shl_code=bash,true]val l = List(1,2,3)
var ll = l.map(x => x*x)//返回 ll=(1,4,9)[/mw_shl_code]
这里借用上面的内容,map里面的x => x*x就是一个匿名函数。
如果初学,我们可能不知道为什么要产生匿名函数,因为匿名函数基本上使用 一次,后面就用不到了。##################

这里扩展,写一下Scala函数定义的几种方式
[mw_shl_code=scala,true]package com.persia

object FuncReturnType {
  
   //写法一,始终待返回值
   def add(x:Int,y:Int):Int={
     x+y
   }
   

   def returnUnit():Unit={
     println("another way to return void")
   }
   
   //写法二,省略非Unit返回值;如果没有写返回值,则根据等号后面的东西进行类型推演,此种不提倡
   def test(x:Int)={
      x
   }
   
   //写法三,省略等号,返回Unit
   def returnVoid(){
     println("return void")
   }
   
   //写法四:省略花括号,如果函数仅包含一条语句,那么连花括号都可以选择不写
   def max2(x: Int, y: Int) = if (x > y) x else y
   
   def greet() = println("Hello, world!")
  
   def main(args:Array[String]):Unit ={
      println(add(1,2))
      println(test(1))
   }

}[/mw_shl_code]


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
对于右箭头,还有一个地方用到就是
匹配模式语句case与后面表达式的分隔符
例如
a match {
case 1 => "match 1"
case _ => "match _"
}
从这里让我们对符号是否有了新的理解,其实无论它是什么符号,它只起到分割的作用


第四个符号int=

int=,我们知道变量后面是一个等号是非常常见的,比如a=1,等,变量等于(=)这个确实难以理解。
下面来看下Scala是函数的定义,我们就能明白了,int=的含义

函数定义.png

scala中函数的定义是使用关键字def,然后函数名,括号中参数的定义,更是与传统语言反着来。Scala是参数在前,类型在后,以冒号(:)作为分隔符。返回值则是写在后面,函数的定义与函数体分隔符则是使用等号分割。单从函数的定义,我们就能看出Scala打破了传统的函数定义,除了函数定义,其它还有很多地方,都反映了Scala思想,没有以前Java,c等那么严格。Scala更像是一个思想的自由者,解放者,随心所欲,不管Java,.net,c等如何搞的,它是自成一家。

自成一家当然不止这一处,比如变量定义,for循环,case等都是做了很大的改变。比如:
for(i <- 1 to 5; j <- 1 to 5),for嵌套,这是我们所熟悉的两层for循环。

[mw_shl_code=java,true]for(i=1;i++;i<=5)
{  for(j=1;j++;j<=5)
     {}
}[/mw_shl_code]
在比如for条件过滤。
我们肯定会这样

[mw_shl_code=java,true]for(i=1;i++;i<=5)
{  for(j=1;j++;j<=5)
     {
      if (!(i==3&&j==3)))
          {
                if(i!=2 || j!=2)
                 {
                  }
          }
     }
}[/mw_shl_code]
那么Scala如何表达
[mw_shl_code=scala,true]for(i<- 1 to 5; j <- 1 to i;if (!(i==3&&j==3)); if(i!=2 || j!=2)){

}[/mw_shl_code]
当然还有更多,大家可以在深入了解下
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
比如:
去掉了函数体定义时的“=”的函数一般称之为“过程”,过程函数的结果类型一定是
Unit。因此,有时定义函数时忘记加等号,结果常常是出乎你的意料的。
如:
def f(a:Int) {
println(a)
}
println(f(1))
输出结果:
1
()
没有返回值的函数的默认返回值是Unit。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

第五个“_”

在scala 中,符号“_”相当于java 中的通配符“*”。这个有很多的含义

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*_)。
又如要对缓冲数组ArrayBuffer b排序,可以这样:
val bSorted = b.sorted(_
4、在元组中,可以用方法_1, _2, _3访问组员。如a._2。其中句点可以用空格替代。

5、使用模式匹配可以用来获取元组的组员,例如
val (first, second, third) = t
但如果不是所有的部件都需要,那么可以在不需要的部件位置上使用_。比如上一例中val (first, second, _) = t

6、还有一点,下划线_代表的是某一类型的默认值。
对于Int来说,它是0。
对于Double来说,它是0.0
对于引用类型,它是null。(引:知乎黄辉煌


############################
进一步补充:
:::运算符
:::(三个冒号)表示List的连接操作,比如:

[mw_shl_code=scala,true]val a = List(1, 2)  
val b = List(3, 4)  
val c = a ::: b  [/mw_shl_code]

其中a,b保持不变,a和b连接产生一个新表List(1,2,3,4),而不是在a上面做add操作。
Scala中的List不同于Java的List,Java声明final List javaList,表示javaList一旦初始化,那么不能再为它赋值,但是它其中的元素可以变化,


::运算符

::(两个冒号)表示普通元素与List的连接操作,比如:

[mw_shl_code=bash,true]val a = 1  
val b = List(3, 4)  
val c = 1 :: b  [/mw_shl_code]

则c的结果是List(1,3,4),需要注意的是,1:: b操作,::是右侧对象的方法,即它是b对象的方法,而::左侧的运算数是::方法的参数,所以1::b的含义是b.::(1)

来自:about云(www.aboutyun.com)
作者:pig2



下一篇
spark开发基础之从关键字入门Scala
http://www.aboutyun.com/forum.php?mod=viewthread&tid=20223








已有(19)人评论

跳转到指定楼层
空空未空 发表于 2016-11-7 19:05:03
不错,很基础
回复

使用道具 举报

tanwen19932 发表于 2016-11-7 20:11:00
=.=果然是基础~
回复

使用道具 举报

小伙425 发表于 2016-11-8 09:31:59
很基础,但是很详尽,LZ辛苦啦 收藏啦
回复

使用道具 举报

w517424787 发表于 2016-11-8 11:43:33
不错,辛苦楼主,可以在整理些,<:  >: <% +T -T ,这些看的最头疼!
回复

使用道具 举报

sdtm1016 发表于 2016-11-9 10:53:19
非常不错,开始学习时,早点看到这篇就好了
回复

使用道具 举报

George-zqq 发表于 2016-11-21 11:00:37
不错的入门基础
回复

使用道具 举报

123下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条