scala 介绍
scala 基于JVM的语言,静态类型,和java互相操作
使用
;可写可不写
- 变量 : var
- 常量 : val
函数:
|
|
函数-头等公民
Scala 中函数为头等公民,你不仅可以定义一个函数然后调用它,而且你可以写一个未命名的函数字面量,然后可以把它当成一个值传递到其它函数或是赋值给其它变量。
(x :Int ) => x +1
这是个函数字面量,它的功能为+1. 符好 => 表示这个函数将符号左边的东西(本例为一个整数),转换成符号右边的东西(加 1)。我们了解到了函数字面量的基本概念,它可以作为参数传递个其它函数,比如很多 Scala 的库允许你使用函数作为参数,比如 foreach 方法,它使用一个函数参数,为集合中每个运算调用传入的函数。
123456789scala> val someNumbers = List ( -11, -10, - 5, 0, 5, 10)someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10)scala> someNumbers.foreach((x:Int) => println(x))-11-10-50510再比如,Scala 的集合也支持一个 filter 方法用来过滤集合中的元素,filter 的参数也是一个函数,比如:
12scala> someNumbers.filter( x => x >0)res1: List[Int] = List(5, 10)
函数–函数字面量的一些简化写法
- Scala 提供了多种方法来简化函数字面量中多余的部分,比如前面例子中 filter 方法中使用的函数字面量,完整的写法如下:
(x :Int ) => x +1
,首先可以省略到参数的类型,Scala 可以根据上下文推算出参数的类型,函数定义可以简化为:(x) => x +1
这个函数可以进一步去掉参数的括号,这里的括号不起什么作用x => x +1
- Scala 还可以进一步简化,Scala 允许使用“占位符”下划线”_”来替代一个或多个参数,只要这个参数值函数定义中只出现一次,Scala编译器可以推断出参数。比如:
|
|
- 前面例子中我们使用“” 来代替单个的参数,实际上你也可以使用“”来代替整个参数列表,比如说,你可以使用 print 来代替 println ().someNumbers.foreach(println _)。
Scala 编译器自动将上面代码解释成:someNumbers.foreach( x => println (x))
因此这里的“” 代表了 Println 的整个参数列表,而不仅仅替代单个参数。当你采用这种方法使用“”,你就创建了一个部分应用的函数(partially applied function)。 在 Scala 中,当你调用函数,传入所需参数,你就把函数“应用”到参数。 比如:一个加法函数。
123scala> def sum = (_:Int) + (_ :Int) + (_ :Int)sum: (Int, Int, Int) => Intscala> sum (1,2,3) res0: Int = 6一个部分应用的函数指的是你在调用函数时,不指定函数所需的所有参数,这样你就创建了一个新的函数,这个新的函数就称为原始函数的部分应用函数,比如说我们固定 sum 的第一和第三个参数,定义如下的部分应用函数:
123scala> val b = sum ( 1 , _ :Int, 3)b: Int => Int = <function1>scala> b(2) res1: Int = 6变量 b 的类型为一函数,具体类型为 Function1(带一个参数的函数),它是由 sum 应用了第一个和第三个参数,构成的。调用b(2),实际上调用 sum (1,2,3)。
可变参数,命名参数
重复参数
- Scala 在定义函数时允许指定最后一个参数可以重复(变长参数),从而允许函数调用者使用变长参数列表来调用该函数,Scala 中使用“*”来指明该参数为重复参数。例如:
|
|
- 在函数内部,变长参数的类型,实际为一数组,比如上例的 String * 类型实际为 Array[String]。 然而,如今你试图直接传入一个数组类型的参数给这个参数,编译器会报错:
|
|
- 为了避免这种情况,你可以通过在变量后面添加 _*来解决,这个符号告诉 Scala 编译器在传递参数时逐个传入数组的每个元素,而不是数组整体。
|
|
命名参数
- 通常情况下,调用函数时,参数传入和函数定义时参数列表一一对应。
|
|
- 使用命名参数允许你使用任意顺序传入参数,比如下面的调用:
|
|
条件表达式
|
|
循环
|
|
类:一个源文件中可以有多个类,并且都是public级别
|
|
构造函数
|
|
继承
|
|
抽象类
- 重写不是抽象类的方法: 在方法前面加一个override
|
|
trait
- 字段和行为的集合
- 混入类中
- 通过with关键字,一个类可以扩展多个特质
- 可以和jdk1.8中的接口对比学习,trait就是带有具体实现的接口
|
|
trait 可以继承trait则第一个trait则是声明,第二个trait可以实现第一个trait里面的抽象方法
一个类可以有多个with来实现trait
apply
- scala没有静态的修饰符,但object下的成员都是静态的 ,若有同名的class,这其作为它的伴生类。在object中一般可以为伴生类做一些初始化等操作,如我们常常使用的val array=Array(1,2,3) (ps:其使用了apply方法)
- apply的用法
|
|
package
- 包package com.xx.data
- 支持嵌套,下层可以访问上层作用域中的名称
- 可串联
- 顶部标记
- 包对象
- 包可见性
- 包在任何地方都可以引入,作用域至该语句所在块的末尾
- 重命名引入(xx = > yy)
- 隐藏方法(xx=>_)
- 自动引入(java.lang. scala. Predef._)
模式匹配match
非常优秀的case
|
|
case class
多用在模式匹配中
- 构造器中的每一个类型都为val,不建议用var
- 不用new就可以直接产生实例
|
|
高阶函数
- 一个简单的demo
|
|
- 函数作为参数
集合
- List:不变的
val l = list(1,2,3,4,5)
,还有可变的 - Set:
val s = Set(1,2,1)
返回的是1 2不能有重复 - 元组:
|
|
- Map
|
|
集合操作
foreach
l.foreach(3*_)
没有返回值filter 过滤
l.filter(x=>x%2==0)
zip 聚合:例如a和b都是集合:
a zip b
则一一对应的聚合partition:列表分割
123l=List(1,2,3,4,5,6)l.partition(_%2 == 0)//得到两个小的集合:List(1,3,5) List(2,4,6)flatten:扁平化
List(List("a","b","c"),List("c","d")).flatten
得到结果是List(a,b,c,d)faltMap(flatten + Map)
1234val l = List(List(1,2),List(3,4))l.flatMap(x=>x.map(_*2))//得到结果意思是,先把集合里面的数据乘以2在压平List(2,4,6,8)
泛型
- 泛型类
class pair[T,S](val first:T,val second:S)
- 泛型方法
def compute[T](list:List[T])=...
隐式转换
- 位于源目标类型的伴生对象中的隐式函数
- 位于当前作用域可以以单个标识符指代的隐式函数
|
|