**
Scala概述
**
1.什么是Scala
编程语言,java shell javascript
函数式编程:
函数式编程是一种编程思想,主要的思想把运算过程尽量写成一系列的函数调用。
Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性。
Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。
scala是对java的进一步封装,基于java来开发的。
scala编译后是.class字节码文件,并运行在jvm上。
2.为什么要学Scala
优雅:这是框架设计师第一个要考虑的问题,框架的用户是应用开发程序员,API是否优雅直接影响用户体验。
速度快:Scala语言表达能力强,一行代码抵得上Java多行,开发速度快;Scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多。
scala语言风格简洁,也很可能降低了可读性,所以学习及以后开发过程中,都需要有良好的代码规范。
能融合到Hadoop生态圈:Hadoop现在是大数据事实标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。JVM语言大部分可能会想到Java,但Java做出来的API太丑,或者想实现一个优雅的API太费劲。
2.Scala基础
1. 常用类型
Scala和java一样,
AnyVal
有7种数值类型:Byte、Char、Short、Int、Long、Float和Double(没有基本类型和包装类型的区分)
2种非数值类型: Boolean 和 Unit
注意:Unit表示无值,相当于java中的void。用作不返回任何结果或者结果为空的类型。Unit类型只有一个实例值,写成()。(小括号)
String是属于引用类型
AnyRef
2.自动识别类型:
Scala编译器会自动推断变量的类型,必要的时候可以指定类型
scala> val scala1 = 88
scala1: Int = 88
scala> val scala2:Double = 88.88
scala2: Double = 88.88
scala> val scala2 = 88.88
scala2: Double = 88.88
3.Val与var定义变量
Val定义的变量相当于Java中被final修饰的变量——不可变
推介使用val
scala> val scala2 = 66.66
scala2: Double = 66.66
scala> scala2 = 55.5
<console>:12: error: reassignment to val
scala2 = 55.5
^
Var定义的变量时——可变的
scala> var sa = 5
sa: Int = 5
scala> sa = 6
sa: Int = 6
Lazy val + 变量名
注意:lazy关键字不能修饰 var类型的变量
scala> lazy val age = 24
age: Int = <lazy>
scala> age
res1: Int = 24
Java中的通配符时*; scala中的通配符时_
scala> var sa:String =_
sa: String = null
scala> var sa:Unit =_
sa: Unit = ()
scala> var sa:Int =_
sa: Int = 0
只能用法var定义,类型不同返回的默认值也不同
定义一个数组
scala> var arr = Array[Int](5,4,7,6)
arr: Array[Int] = Array(5, 4, 7, 6)
- 条件表达式
条件表达式都是有返回值的
var i = 1
val unit1 = if(i>0){
"我是返回值"
}
println(unit1)
//我是返回值
返回值的类型,分支类型不同,返回值类型是各分支的返回值类型的父类型。如果缺少了else分支,那么该分支的返回值类型是Unit,值是()
(Int和Unit,返回值类型是AnyVal,Int和String,返回值类型是Any)
val unit:Any = if(i>1){
i
}else{
"woshi else"
}
返回什么值? 是由每一个分支的最后一行返回值决定的
什么时候可以省略分支的大括号:分支的结构只有一行,
val unit3:Any = if(i>1){
i
}else
"woshi else"
println(unit3)
//woshi else
5.块儿表达式
object BlockDemo {
def main(args: Array[String]): Unit = {
var i = 3
var res =if(i>3){
1
}else if(i<=3){
-1
}else{
0
}
println(res)
}
}
Res 的值就是块表达式的值
6.循环语句
关键标识: <-
可以使用增强for循环,直接操作元素
使用to和until,可以使用下标来操作集合
scala> var arr = Array[Int](5,4,7,6)
arr: Array[Int] = Array(5, 4, 7, 6)
scala> for(i <- 0 to arr.length-1) println(arr(i))
5
4
7
6
scala> for(i <- 0 until arr.length) println(arr(i))
5
4
7
6
scala> for(i <- 0 until arr.length){
| if(arr(i)%2==1) println(arr(i))
| }
5
7
for可以带守卫,可以用yield推导式
scala> var dd = for (i <- arr) yield i * 10
dd: Array[Int] = Array(50, 40, 70, 60)
嵌套for循环
scala> for (i <- 0 to 3; j <- 0 to 3 if (i != j)) print(i * 10 + j + " ")
1 2 3 10 12 13 20 21 23 30 31 32
7.While循环
scala> var i = 0
i: Int = 0
scala> while (i < 10) {
| i += 1
| print(i + " ")
| }
1 2 3 4 5 6 7 8 9 10
scala> do {
| i -= 1
| print(i + " ")
| } while (i < 10 && i > 0)
9 8 7 6 5 4 3 2 1 0
3.方法和函数
1. 调用方法
scala> var a = 3
a: Int = 3
scala> var b = 4
b: Int = 4
scala> a.+(b)
res13: Int = 7
scala> a+b
res14: Int = 7
object defDemo {
def stra()={
"wudangpei"
//返回Until类型
println("wudangpei")
}
def strb={
var bbb = "wudangpei"
bbb
}
def resa():String={
return "华山派"
}
def sum(a:Int,b:Int): Int ={
a+b
}
def SUM(j:Int*):Int= {
var p = 0
for (i <- j) {
p += i
}
p
}
def result(x:Int):Int={
if(x==0){
0
}else{
x*result(x-1)
}
}
def main(args: Array[String]): Unit = {
println("-----------------------------")
//定义空参方法有()调用是可省略
println(stra())
println(stra)
println("-----------------------------")
//定义空参方法没有()调用时不能加()
println(strb)
println("-----------------------------")
//方法体中有return必须有返回值类型
println(resa())
println("-----------------------------")
//
var res = sum(4,6)
println(res)
println(SUM(1,2,3,4,5))
println("-----------------------------")
//递归调用的方法必须有返回值类型
println(result(5))
}
}
方法总结:
使用def关键字来定义方法
方法的参数列表,是自定义的,可以为空,可以为可变参数
方法的返回值类型,可以不写,编译器会自动推导出来,但是递归调用的方法和有return关键字修饰的方法,必须要有返回值类型。
方法必须被显示调用,不能作为最终的表达式存在。空参方法定义时,省略了(),属于空参方法调用。
调用空参方法时,可以省略参数列表的(),但是如果定义空参方法时没有添加参数列表(),则在调用时,不能加()。
返回值类型是什么?最后一行代码的返回值决定的。
4.定义函数
函数表示:=>
1)匿名函数
scala> (a:Int,b:Int) => a+b
res15: (Int, Int) => Int = <function2>
scala> res15(3,6)
res16: Int = 9
2)第一种定义函数方法
scala> var fun1 = (a:Int,b:Int) => a+b
fun1: (Int, Int) => Int = <function2>
3)第二种定义函数方法
scala> val fun2:(Int,Int) => Int = (a,b) => a+b
fun2: (Int, Int) => Int = <function2>
scala> fun2(5,4)
res0: Int = 9
scala> def way(w:(Int,Int) => Int) = w(8,4)
way: (w: (Int, Int) => Int)Int
scala> val fun = (a:Int,b:Int) => a*b
fun: (Int, Int) => Int = <function2>
scala> way(fun)
res2: Int = 32
通配符将方法转为函数
scala> def way2(a:Int,b:Int) : Int =a*b
way2: (a: Int, b: Int)Int
scala> var fun2 = way2 _
fun2: (Int, Int) => Int = <function2>
4)函数与方法的区别
在函数式编程语言中,函数是“头等公民”,它可以像任何其他数据类型一样被传递和操作
函数和变量,类,对象,一个级别,方法,要归属于类或者对象
区别和联系:
方法用def关键字定义,函数的标识 =>
方法不能作为最终的表达式存在,但是函数可以,返回函数的签名信息
方法和函数调用的时候都需要显示的传入参数
函数可以作为方法的参数,和返回值类型。
4.元组——tuple
1) 创建元组
scala> var a = new Tuple3(12.0,"fs",55)
a: (Double, String, Int) = (12.0,fs,55)
2) 获取元组中的值
scala> var m,(a,b,c,d)=("scala",'B',5.64,55)
m: (String, Char, Double, Int) = (scala,B,5.64,55)
a: String = scala
b: Char = B
c: Double = 5.64
d: Int = 55
scala> var m1=m._1
m1: String = scala
scala> var m1=m._2
m1: Char = B
scala> var m1=m._3
m1: Double = 5.64
scala> var m1=m._4
m1: Int = 55
5.WorldCount
scala> var arr = Array("hello love pig","love dog pig","hello love")
arr: Array[String] = Array(hello love pig, love dog pig, hello love)
scala> val d1 = arr.map((x:String) => x.split(" "))
d1: Array[Array[String]] = Array(Array(hello, love, pig), Array(love, dog, pig), Array(hello, love))
scala> val d1 = arr.map((x:String) => x.split(" ")).flatten
d1: Array[String] = Array(hello, love, pig, love, dog, pig, hello, love)
scala> val d2 = d1.map((x:String) => (x,1))
d2: Array[(String, Int)] = Array((hello,1), (love,1), (pig,1), (love,1), (dog,1), (pig,1), (hello,1), (love,1))
scala> val d3 = d2.groupBy(t=>t._1)
d3: scala.collection.immutable.Map[String,Array[(String, Int)]] = Map(dog -> Array((dog,1)), pig -> Array((pig,1), (pig,1)), love -> Array((love,1), (love,1), (love,1)), hello -> Array((hello,1), (hello,1)))
scala> val d4 = d3.map(t=>(t._1,t._2.size))
d4: scala.collection.immutable.Map[String,Int] = Map(dog -> 1, pig -> 2, love -> 3, hello -> 2)
object WordCount {
def main(args: Array[String]): Unit = {
//造一个数组
var arr = Array("hello dog love","pig dog love","love hello")
println(arr)
//切分 flatMap代替了先map后flatten
val res1 = arr.flatMap((a:String) => a.split(" "))
println(res1)
//与(x,1)组合
val res2 = res1.map((x:String) => (x,1))
println(res2)
val res3 = res2.groupBy(t=>t._1)
println(res3)
val result = res3.map(t=>(t._1,t._1.size))
println(result)
//Map(dog -> 3, pig -> 3, love -> 4, hello -> 5)
}
}