Scala快速概览
IDEA工具安装及scala基本操作
目录
1、 确保Java安装成功
[hadoop@spark01-61cdh scala-2.10.4]$ java -version
java version “1.7.0_111”
[hadoop@spark01-61cdh scala-2.10.4]$ echo $JAVA_HOME
/opt/modules/jdk1.7.0_6
[hadoop@spark01-61cdh modules]$ tar -zxf
/opt/software/scala-2.10.4.tgz -C /opt/modules/
3、 配置Scala环境变量
export SCALA_HOME=/opt/modules/scala-2.10.4/bin
export PATH=$PATH:$SCALA_HOME
[hadoop@spark01-61cdh scala-2.10.4]$ source /etc/profile
4、 启动Scala命令行
直接输入scala,回车就进入scala命令行。
[hadoop@spark01-61cdh -bash: scala: [hadoop@spark01-61cdh [hadoop@spark01-61cdh [hadoop@spark01-61cdh Welcome to Scala Type in expressions Type :help for more scala> |
二、 Windows下安装IDEA的Scala插件
1、 在IDEA中File打开Setting
左边选择Plugins,在右侧的查找框中找Scala,看是否已经安装了,如果没有安装,则点击下面的“Install
JetBrains Plugin…”进行安装Scala插件。
搜索Scala,右侧点击Intall进行下载安装。
3、 重启IDEA后,新建项目对话框,就可以看到Scala模板。
1、 下载Window版本的Scala-2.10.4
Scala SDK版本选择时,点击Create按钮,在打开的对话框中点击Browse,找到Scala目录下的lib目录。
File中点击Project Structure,左侧选择Modules,在右侧代码目录下创建如下目录。
创建一个包:scala.com.chybinmy.scala.spark
这里选择Object类型。
6、 写main方法
<b>package </b>scala.com.chybinmy.scala.spark<br/> <br/> <i>/**<br/> * Created by 鸣宇淳 </i><i>on 2016/9/27.<br/> */<br/> </i><b>object </b>HelloWorld {<br/> <b>def </b>main(args: Array[String]) {<br/> <i>println</i>(<b>"Hello World!"</b>)<br/> }<br/> } |
在代码编辑页面右击选择Run “Hello World”,进行运行,可以看到输出了“Hello World!”
四、 Scala基本语法
<b>def </b>max(x: Int, y: Int): Int = {<br/> <b>if </b>(x > y)<br/> x<br/> <b>else<br/> </b>y<br/> } |
² def关键字是定义一个max
² max是函数名称
² x是第一个参数名,:Int是指定参数x的类型为Int,y是第二个参数名称
² 小括号后面的:Int是表示函数返回值为Int
² =后面是函数体,=符号可以理解为将后面的函数体赋值给前面的函数定义。当函数显示地指定了返回值时,这个=是不可以省略的,如果没有显示定义返回值可以省略这个=。
² Scala和JavaScripte里类似,一行的结束可以不用分号;
² Scala的函数可以没有return,运行时,执行的最后一条语句的返回值就是函数的返回值。
在Scala命令行中运行函数定义和调用:
scala> def max(x:Int,y:Int):Int={ | if(x>y) | x | else | y | } max: (x: Int, y: Int)Int scala> max(2,3) res0: Int = 3 |
<b>def </b>add1() = {<br/> <i>println</i>(<b>"add1...."</b>)<br/> }<br/> <br/> <i>//</i><i>无参数的函数可以省略</i><i> =<br/> </i><b>def </b>add2() {<br/> <i>println</i>(<b>"add2...."</b>)<br/> }<br/> <br/> <i>//无返回值的函数,返回值其实是</i><i>Unit类型的,<br/> </i><i>// Unit可以省略,就像第一个</i><i>add1一样<br/> </i><b>def </b>add3(): Unit = {<br/> <i>println</i>(<b>"add3...."</b>)<br/> } |
调用时,如果函数没有参数,可以省略()
scala> | println(“add3….”) | } add3: ()Unit scala> add3 add3…. |
<i>//当函数体只有一行代码时,可以将花括号</i><i>{}省略<br/> </i><i>//所以当无参数、无返回值、一行代码的函数,可以写为这样<br/> </i><b>def </b>add4() = <i>println</i>(<b>"add3...."</b>) |
<i>//</i><i>一个函数</i> <b>def </b>add5(x: Int, y: Int) = x + y <i> </i> <i>//</i><i>改为匿名函数<br/> </i>(x: Int, y: Int) => x + y |
匿名函数的函数体前面要用 => 符号。
<i>//将匿名函数赋值给常量<br/> </i><b>val </b><i>add6</i>=(x: Int, y: Int) => x + y |
<i>//一个无参数函数<br/> </i><b>def </b>add8() = <i>println</i>(<b>"add8"</b>)<br/> <i>//一个有参数函数<br/> </i><b>def </b>add9(x: Int, y: Int) = x + y<br/> <br/> <i>//将无参数函数赋值给常量<br/> </i><b>val </b><i>add10 </i>= <i>add8</i>;<br/> <i>//将有参数函数赋值为常量,必须加 _<br/> </i><b>val </b><i>add11 </i>= <i>add9 </i>_; <i> </i> |
如果想将上面的add6传递给另外一个函数add7,add7应该定义如下:
<i>//将函数赋值给函数<br/> </i><b>def </b>add7(f: <a>(Int, Int) => Int</a>): Int = {<br/> f(3, 8)<br/> } |
上面的(Int,Int)=>Int是定义了一个类型,类型是个匿名函数,参数f的类型就是个函数,这个函数的输入参数是两个Int类型的值,返回值也是个Int类型的值,另外add7函数的返回值也是个Int类型。
函数体中f(3,8)是说,函数体是去执行输入的那个匿名函数。
//name参数可以不传递,不传递时使用默认值:xiaoming def sayName(name: String = “xiaoming”) { println(“Hello!” + name) } |
定义函数时可以给参数指定一个默认值,当不传递这个函数时函数体就使用指定的默认值。一般惯例是将有默认值的参数参数列表的最后面。
def printCourse2(course: String*): Unit course.foreach(x => println(x)) } def printCourse(course: var txt = “”; course.foreach(x => (txt += (x + “,”))) println(“input:” + txt) } |
在Scala中,定义函数时,最后一个参数可以变长,变长的意思是:参数的个数不确定,可以有很多个,类型后面添加一个*字符表示这个参数是可以变长的,调用时如下:
printCourse2(“a”,”b”,”c”)
² 1 to
10:循环1到10,包括1和10,包头包尾。
² 1.to(10)
同1 to 10
² 1
until 10 : 循环1到10,不包含10,包头不包尾。
² 1.until(10)
同 1 until 10
² Range(1,10)
同 1 to 10
² Range(1,10,2)
是从1到10,步长为2,就是循环1、3、5、7、9
(2)
for循环
def main(args: var sum = 0; for (i <- 1 to 10) { sum += i } println(sum) } |
参与循环的变量i与i取值范围之间用<-表示。
1 to 10明确表明了取值范围是1到10,包括1和10。
sum = 0 for (i <- 1 until 10) sum += i println(sum) |
until是不包括10的,取值是1到9
for (c <- println(c) |
遍历字符串并不需要下标。
(3)
for循环嵌套
<b>for </b>(i <- 1 to 3; j <- 1 to 3)<br/> <i>println</i>(i.toString + j.toString) |
(4)
for循环中判断
for (i <- 1 to 3; j <- 1 to 3 ; if i>j)<br/> <i>println</i>(i.toString + j.toString) |
(5)
break、coutinue
Scala中没有break和coutinue关键字,如果想实现类似功能,可以使用scala.util.control.Breake来是实现。
object BreakDemo def main(args: Array[String]) { //定义一个集合 val numList = List(1, 2, 3, 4, 5, 6, 7, 8) //实例化一个Breaks对象, val loop = new Breaks loop.breakable( //将循环放入loop.breakable中 for (num <- println(num) if(4==num) { //使用loop.break()方法来实现跳出 loop.break() } } ) } } |
² 定长数组定义:val list=Array(1,2,3,4,5)
或者 val list2=new
Array[Int](5)
² 赋值:list(0)=11。下标用小括号来指定,而不像Java中一样用方括号。
² 变长数组定义:val
listBuffle=scala.collection.mutable.ArrayBuffer[Int](1,2,3)
² 添加一个元素:listBuffle+=2 添加一个元素2。
² 添加多个元素:listBuffle++=Array(5,6,7)
添加了三个元素到变长数组里。
listBuffle+=(8,9,10) 添加了一个元组。
² 插入元素:listBuffle.insert(0,0)在0的位置插入一个值0。
² 删除元素:listBuffle.remove(4) 删除4位置的元素。
scala> listBuffle.toArray
res17: Array[Int] = Array(0, 1, 2, 3, 5, 6,
7, 8, 9, 10)
for(i<-listBuffle) println(i)
listBuffle.mkString(“|”) 将数组变为字符串,用 | 字符隔开
listBuffle.mkString(“[“,”|”,”]”)
将数组变为字符串,用|隔开,前面添加[,后面添加]。
元组是可以存储不同类型元素的集合。
有两个元素的元组叫二元组。
scala> val tuple=(1,2,4,”a”)
tuple: (Int, Int, Int, String) = (1,2,4,a)
元组在Spark中很常见,比如key、value对可能就是个元组,{1001:”beijing”}
可以用tuple._1获取第一个元素,注意元素的下标从1开始。
for(i<- 1 to tuple.productArity-1 )
println(tuple.productElement(i))
² tuple.productArity是获取元组的长度
² tuple.productElement是获取元组的某一个下标的元素,请注意这里的下标是从0开始。
(1)
Scala集合介绍
² Scala有一个非常丰富、强大可组合的集合库,集合都在scala.collection包中。
² Scala集合中有定长集合和变长集合,定长集合在scala.collection.
immutable中,变长集合在scala.collection.
mutable中
(2)
Scala集合结构
(3)
List集合
² 定义一个List:val list=List(1,2,3,4,5)
² List由head和tail组成:
scala> list.head res34: Int = 1 scala> list.tail res35: List[Int] = |
head是集合中第一个元素,tail是除了head外的其他元素组成的集合,也就是tail是个List集合,tail也有head和tail,如下:
scala> list.tail.tail.tail res36: List[Int] = |
² 空集合用Nil表示,同List()
² 另外一种定义集合方式,是用head和tail方式定义,如下:
//head为1,tail为空集合 scala> var list2: List[Int] = //head为2,tail为一个集合 scala> var list3: List[Int] = //另一种定义方式 scala> var list4: List[Int] = //上面方式可以理解为这种方式 scala> var list5=(1::(2::(3::list3))) list5: List[Int] = |
² List转换为数组
scala> list.toArray
res3: Array[Int] = Array(1, 2, 3, 5)
² List中添加、减少元素
List是定长集合,所以不能添加元素,但是变长List可以添加元素。
//定义一个变长集合 scala> val list2: //添加元素 scala> list2+=2 res4: list2.type = //添加一个元组 scala> list2+=(3,4) res5: list2.type = //添加一个集合 scala> list2++=List(5,6) res6: list2.type = //减少一个元素 scala> list2-=3 res7: list2.type = //减少一个集合 scala> list2–=List(5,4) res8: list2.type = |
² Set中的元素是无序不重复的集合。
² 定义一个Set集合:scala> var
set=Set(1,2,3,4,5)
² 定义要给可变长Set集合:val
set1=scala.collection.mutable.Set[Int]()
² 对变长Set集合,+ 、+=、++=是不同的
set1+1是创建另外一个可变Set集合,内容为添加了一个1。
set1+=1 是在原来的Set集合中添加一个元素1
(5)
Map集合
² Map是键值对的集合
² 定义一个定长Map: scala> val
map=Map(“zhangsan”->20,”lisi”-> 25)
² 获取值
scala> map(“zhangsan”) 是根据key获取值。
scala>
map.getOrElse(“zhangsan”,0) 根据Key获取值,如果是空则返回0。
² 赋值
同Set一样,只有可变的Map集合才能赋值。
–定义一个可变的Map scala> val b: scala.collection.mutable.Map[String,Int] –第一种赋值方式,添加一个wangwu scala> –显示当前b的内容 scala> b res1: –第二种,添加内容方式,用+= scala> b+=(“wangma”->35,”hanliu”->40) –删除内容,用-= scala> |
² 遍历Map
//第一种遍历方法 scala> | println(“key=”+key+”,value=”+value) key=lisi,value=30 key=wangma,value=35 key=hanliu,value=40 key=wangwu,value=35 |
//第二种遍历方式 scala> for(ele | key=lisi,value=30 key=wangma,value=35 key=hanliu,value=40 key=wangwu,value=35 |
//只遍历值 scala> | println(“value=”+ele) value=30 value=35 value=40 value=35 |
//遍历的另外一种方式,value不一定有值时 scala> | key=lisi,value=30 key=wangma,value=35 key=hanliu,value=40 key=wangwu,value=35 |
Java中只能对数值进行模式匹配,但是在Scala中,除了可以对值进行模式匹配外,还可以对类型进行模式匹配,对Array和List的元素进行匹配、对case class进行匹配、甚至对有值或者没有值进行匹配。
<b>package </b>scala.com.chybinmy.scala.spark<i><br/> </i><b>object </b>MatchDemo {<br/> <b>def </b>main(args: Array[String]) {<br/> <i>judge</i>(<b>"A"</b>)<br/> <i>judge</i>(<b>"E"</b>)<br/> }<br/> <br/> <b>def </b>judge(tag: String): Unit = {<br/> tag <b>match </b>{<br/> <b>case </b><b>"A" </b>=> <i>println</i>(<b>"Excellent"</b>)<br/> <b>case </b><b>"B" </b>=> <i>println</i>(<b>"Good"</b>)<br/> <b>case </b><b>"C" </b>=> <i>println</i>(<b>"Just so so"</b>)<br/> <b>case </b>_ => <i>println</i>(<b>"You need word hard"</b>)<br/> }<br/> }<br/> } |
def judge(tag: String,name:String): Unit = { tag match { case “A” => println(“Excellent”) case “B” => println(“Good”) case “C” => println(“Just so so”) case _ if name.equals(“xiaoming”)=>println(name+”,come on!”) case _ => println(“You } } |
package scala.com.chybinmy.scala.spark object ExceptionTest extends App { try { val i = 1 / 0 } catch { case e: ArithmeticException => throw new case e: Exception => println(e.getMessage) } finally { println(“finally”) } } |
当匹配类型时,case
后面的e为变量名,冒号后面的是要匹配的类型名称。
package scala.com.chybinmy.scala.spark class Person case class Teacher(name: String, subject: String) extends Person case class Student(name: String, classroom: String) extends Person object CaseMathTest { def judge(person: Person): Unit = { person match { case Teacher(name, subject) => println(“Teacher:” + name + “,” + case Student(name, classroom) => println(“Student:” + name + “,” + case _ => println(“error!”) } } def main(args: Array[String]) { judge(new Teacher(“xuanyu”,“spark”)) judge(new Student(“ming”,“7 ban”)) judge(null) judge(new Person) } } |
Scala中的Option是一种特殊的类型,Option有两种值:Some表示有值,None表示没有值。模式匹配Option用于判断某个变量有值还是没有值。
package scala.com.chybinmy.scala.spark object OptionMathDemo { def getGrade(name: String): Unit = { val grades = val g = g match { case Some(course) => println(name case None => println(name + “,no } } def main(args: Array[String]) { getGrade(“xx”) getGrade(“aa”) } } |
<a><b>package </b></a>scala.com.chybinmy.scala.spark<br/> <b>object </b>ExceptionTest <b>extends </b>App {<br/> <b>try </b>{<br/> <b>val </b>i = 1 / 0<br/> }<br/> <b>catch </b>{<br/> <b>case </b>e: ArithmeticException => <b>throw new </b>RuntimeException(<b>"not zero!"</b>)<br/> <b>case </b>e: Exception => <i>println</i>(e.getMessage)<br/> }<br/> <b>finally </b>{<br/> <i>println</i>(<b>"finally"</b>)<br/> }<br/> } |
输入参数的类型为函数的函数为高阶函数(higher-order function)。
package scala.com.chybinmy.scala.spark object HigherDemo //定义一个高阶函数 def greetin(f: (String) => f(name) } def main(args: Array[String]) { //定义一个函数赋值为常量 val sayHelloFunc = //将函数类型的常量做为参数,传递给高阶函数 greetin(sayHelloFunc, “老王!“) //将一个匿名函数做为参数传递给高阶函数 greetin((name: String) => println(name //省略匿名函数参数的类型 greetin((name) => println(name //如果只有一个参数,可以省略括号 greetin(name => println(“早” + name), “小红“) //List.map是个高阶函数 var list = List(1, 2, 3, 4, 5) println(list) println(list.map((x: Int) => x + 1)) println(list.map(x => x + 1)) //只有一个参数,并函数体中只用到一个这个参数,可以用_表示 println(list.map(_ + 1)) } } |
将函数做为参数传递给另外一个函数,是一种封装。
<b>package </b>scala.com.chybinmy.scala.spark<br/> <br/> <i>//</i><i>定义一个特殊人群类</i><i><br/> </i><b>class </b>SpecialPerson(<b>val </b>name: String)<br/> <i>//</i><i>定义一个学生</i><i><br/> </i><b>class </b>Stu(<b>val </b>name: String)<br/> <i>//</i><i>定义一个老人类</i><i><br/> </i><b>class </b>Older(<b>val </b>name: String)<br/> <br/> <b>object </b>ImplicitDemo {<br/> <b>def </b>main(args: Array[String]) {<br/> <i>//</i><i>将</i><i>Stu</i><i>类型隐式转换为</i><i>SpecialPerson</i><i>类型</i><i><br/> </i><b>val </b>stu = <b>new </b>Stu(<b>"xiaoping"</b>)<br/> <b>val </b>ticket = <i>buySpecialTicker</i>(stu)<br/> <i>println</i>(<b>"Buy ticket:" </b>+ ticket)<br/> <br/> <i>//</i><i>将</i><i>Oler</i><i>类型隐式转换为</i><i>SpecialPerson</i><i>类型</i><i><br/> </i><b>val </b>older = <b>new </b>Older(<b>"laoli"</b>)<br/> <b>val </b>ticket2 = <i>buySpecialTicker</i>(older)<br/> <i>println</i>(<b>"Buy older ticket:" </b>+ ticket2)<br/> }<br/> <br/> <i>//</i><i>买票函数,这个函数定义输入参数是</i><i>SpecialPerson</i><i>类型的</i><i><br/> </i><b>var </b><i>ticketNumber </i>= 0<br/> <b>def </b>buySpecialTicker(p: SpecialPerson): String = {<br/> <i>ticketNumber </i>+= 1<br/> <b>"T-" </b>+ <i>ticketNumber<br/> </i>}<br/> <br/> <i>//</i><i>定义一个隐式转换函数,定义了那些类型可以隐式转换为</i><i>SpecialPerson<br/> </i><b>implicit def </b>objectToSpecialPerson(obj: Object): SpecialPerson = {<br/> <b>if </b>(obj.getClass == <i>classOf</i>[Stu]) {<br/> <b>val </b>stu = obj.asInstanceOf[Stu]<br/> <b>new </b>SpecialPerson(stu.name)<br/> }<br/> <b>else if </b>(obj.getClass == <i>classOf</i>[Older]) {<br/> <b>val </b>older = obj.asInstanceOf[Older]<br/> <b>new </b>SpecialPerson(older.name)<br/> }<br/> <b>else<br/> new </b>SpecialPerson(<b>"</b><b>未知名字</b><b>"</b>)<br/> }<br/> } |
这段程序是特殊人群买票的例子,objectToSpecialPerson定义了Stu类和Older类可以隐式转换为SpecialPerson类,所以虽然buySpecialTicker函数的输入参数为SpecialPerson类型,但是调用时,可以传递Stu和Older类型的值进去,因为自动做了隐式转换。
隐式转换允许手动指定将某种类型的对象转换为其他类型的对象,最核心的就是定义了隐式转换函数。
隐式转换的强大之处就在于可以在不知不觉中加强了现有类型的功能,也就是说可以为某一个类定义一个加强版的类,并定义相互转换,从而让源类可以调用加强版类里的方法。
Scala默认会使用两种隐式转换:
² 一种是从源类型或者目标类型的伴生对象内,找隐式转换函数
² 一种是当前程序的作用域内找隐式转换函数。
如果其他两种方式都找不到,那就要手动导入了。如:
var sqlContext=new SQLContext(sc)
import sqlContext.implicit._
当在如下情况下,会尝试进行隐式转换:
² 调用某个函数,但是给函数传入的参数的类型与函数定义的接收类型不匹配。
² 使用某个类型的对象,调用某个方法,而这个方法并不存在于该类型时
² 使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型与方法定义的参数类型不匹配时
Scala中有一种特殊的类型是Option,用来表示那种有肯能存在也肯能不存在的值,Option有两种值,一种是Some,表示有值,一种是None,表示没有值。
Option通常会用于模式匹配中,用于判断某个变量有值或者没有值,比Null更加简洁
Scala中的Trait是一种特殊的概念,类似于Java中的接口,在Trait中可以用来定义抽象方法。类可以使用extends关键字继承trait,继承后必须实现其中的抽象方法,实现时不需要使用override关键字,虽然Scala不支持对类进行多继承,但是支持使用with来多重继承trait。
trait还可继承于trait。
附件列表
转发申明:
本文转自互联网,由小站整理并发布,在于分享相关技术和知识。版权归原作者所有,如有侵权,请联系本站 top8488@163.com,将在24小时内删除。谢谢