java和scala可以无缝混编(都是基于JVM)
类型推测(不必指定类型,自动推测类型)
支持并发和分布式(Actor)
特质:trait(集结了java中抽象类和接口的产物)
模式匹配(match case :类似于java中的switch case)
高阶函数(参数时函数或者返回值是参数)
本教程介绍在Windows下安装Scala2.10版本。安装包可以去官网下载。Scala官网。
下载完成之后,解压在电脑合适位置(记住该位置)。然后配置环境变量(和java配置环境变量一样)
新建一个系统变量SCALA_HOME,值是Scala安装包的位置。
编辑Path环境变量,添加;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin
此时scala安装完毕,使用win+r输入cmd打开命令行,然后输入scala -version可以看到安装的scala的版本号。测试成功。
1)、数据类型
Byte 8bite的有符号数字,范围在-128 – 127
Short 16bite的有符号数字,范围值在-32868 – 32767
Int 32bite的有符号数字,范围在-21亿 – 21亿
Long 64bite的有符号数字,范围在 负的2的16次方 – 2的16次方
Float 32bite 单精度浮点数
Double 64bite 双精度浮点数
Char 16bite Unicode字符
String 字符串
Boolean 布尔类型
Unit 表示无值,和其他语言的void相同
Null 空值或者空引用
Nothing 所有其他类型的子类型,表示没有值
Any 所有类型的超类,任何实例都属于Any类型。类似于java的Object
AnyRef 所有引用类型的超类
AnyVal 所有值类型的超类
Nil 长度为0的List
定义变量或者常量的时候,可以写上返回类型,也可以不写,如下:
变量:var age:Int = 20或者var age2 = 18
常量:val age:Int = 20或者val age2 = 18(常量不可以再次赋值)
创建类:
class Person{
val name = "zhangsan"
val age = 18
def sayName() = {
"my name is "+ name
}
}
创建对象:
object Lesson_Class {
def main(args: Array[String]): Unit = {
val person = new Person()
println(person.age);
println(person.sayName())
}
}
用法与java基本相同
val age =18
if (age < 18 ){
println("no allow")
}else if (18<=age&&age<=20){
println("allow with other")
}else{
println("allow self")
}
讲解Scala的循环之前,先讲解Scala的一个特性:until和to(主要区别是:until前闭后开,to前闭后闭)
println(1 until 10 ) //不包含最后一个数,打印 1,2,3,4,5,6,7,8,9
println(1 until (10 ,3 )) //步长为3,从1开始打印,打印1,4,7
println(1 to 10 ) //打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
println(1 to (10 ,2)) //步长为2,从1开始打印 ,1,3,5,7,9
在逻辑上,Scala中的循环跟java中的循环一样,只是使用的方式有些区别,下面分别做介绍。
for循环(九九乘法表)
for(i <- 1 until 10 ;j <- 1 until 10){
if(i>=j){
print(i +" * " + j + " = "+ i*j+" ")
}
if(i==j ){
println()
}
}
与java中不一样的是,for里面可以加判断,如下(判断要用分号分割,可以使用判断来跳出循环,Scala中没有break和countiue,需要使用的话,需要调用javaApi):
for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
println(i)
}
while与dowhile跟java中判断逻辑一样,下面贴个简单的while例子:
var index = 0
while(index < 100 ){
println("第"+index+"次while 循环")
index += 1
}
注意点:scala中不能使用count++,count—只能使用count = count+1 ,count += 1
for循环用yield 关键字返回一个集合val list = for(i <- 1 to 10 ; if(i > 5 )) yield i
for循环中可以加条件判断,分号隔开
函数格式:
def 函数名(变量名:变量类型,...):返回值类型 = {
函数体
}
下面是Scala函数的一些规则和注意点:
函数定义语法 用def来定义
可以定义传入的参数,要指定传入参数的类型
方法可以写返回值的类型也可以不写,会自动推断,有时候不能省略,必须写,比如在递归函数中或者函数的返回值是函数类型的时候。
scala中函数有返回值时,可以写return,也可以不写return,会把函数中最后一行当做结果返回。当写return时,必须要写函数的返回值。
如果返回值可以一行搞定,可以将{}省略不写。(def fun1 (a : Int , b : Int)= a+b)
传递给方法的参数可以在方法中使用,并且scala规定方法的传过来的参数为val的,不是var的。
如果去掉方法体前面的等号,那么这个方法返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit.假设,里面的逻辑最后返回了一个string,那么这个返回值会被转换成Unit,并且值会被丢弃。
递归函数(求阶乘)
def fun2(num :Int) :Int= {
if(num ==1)
num
else
num * fun2(num-1)
}
默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值。
如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称。
def fun3(a :Int = 10,b:Int) = {
println(a+b)
}
fun3(b=2)
多个参数用逗号分开。
def fun4(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun4(1,2,3,4))
匿名函数分为有参匿名函数、无参匿名函数、有返回值的匿名函数。(可以将匿名参数的返回给一个val声明的值,匿名函数不能显式的声明返回值)
//有参数匿名函数
val value1 = (a : Int) => {
println(a)
}
value1(1)
//无参数匿名函数
val value2 = ()=>{
println("我爱Angelababy")
}
value2()
//有返回值的匿名函数
val value3 = (a:Int,b:Int) =>{
a+b
}
println(value3(4,4))
def fun5(num:Int)={
def fun6(a:Int,b:Int):Int={
if(a == 1){
b
}else{
fun6(a-1,a*b)
}
}
fun6(num,1)
}
println(fun5(5))
偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
def log(date :Date, s :String)= {
println("date is "+ date +",log is "+ s)
}
val date = new Date()
//想要调用log,以上变化的是第二个参数,可以用偏应用函数处理
val logWithDate = log(date,_:String)
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")
函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型都是函数的函数。
//函数的参数是函数
def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
f(a,100)
}
def f(v1 :Int,v2: Int):Int = {
v1+v2
}
println(hightFun(f, 1))
//函数的返回是函数
//1,2,3,4相加
def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
def f2 (v1: Int,v2:Int) :Int = {
v1+v2+a+b
}
f2
}
println(hightFun2(1,2)(3,4))
//函数的参数是函数,函数的返回是函数
def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
f
}
println(hightFun3(f)(100,200))
println(hightFun3((a,b) =>{a+b})(200,200))
//以上这句话还可以写成这样
//如果函数的参数在方法体中只使用了一次 那么可以写成_表示
println(hightFun3(_+_)(200,200))
可以理解为高阶函数的简化
def fun7(a :Int,b:Int)(c:Int,d:Int) = {
a+b+c+d
}
println(fun7(1,2)(3,4))
创建数组:
//创建类型为Int 长度为3的数组
val arr1 = new Array[Int](3)
//创建String 类型的数组,直接赋值
val arr2 = Array[String]("s100","s200","s300")
//赋值
arr1(0) = 100
arr1(1) = 200
arr1(2) = 300
遍历数组:
for(i <- arr1){
println(i)
}
arr1.foreach(i => {
println(i)
})
创建二维数组:
val secArray = new Array[Array[String]](5)
for(index <- 0 until secArray.length) secArray(index) = new Array[String](3)
list是不可变的,对list进行添加删除或者取值等操作均会返回一个新的list。
val list = List(1,3,5,9)
println(list.contains(9))
val dropList = list.drop(2)
dropList.foreach { println }
val reList = list.reverse
reList.foreach { x => print(x + "\t") }
set是一个非重复的集合,若有重复数据,则会自动去重。
val set = Set(1,3,5,8,1,6,5,8)
set.foreach { x => print(x + "\t") }
map是K-V键值对集合。
//创建map
val map = Map(
"1" -> "bj" ,
2 -> "sh",
3 -> "gz"
)
//map遍历
for(x <- map){
println("====key:"+x._1+",value:"+x._2)
}
//遍历key
var keys = map.keys
//获取key的迭代器
var keyIterator = keys.iterator
while(keyIterator.hasNext){
val key = keyIterator.next()
println(key + "\t" + map.get(key).get)
}
与列表一样,与列表不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的。创建过程可加new关键词,也可不加。
//创建二元组,下面两句话效果相同
val t2 = new Tuple2(1,"hello")
val tt2 = (1,"hello")
//创建三元组,下面两句话效果相同
val t3 = Tuple3(2,"bj","come")
val tt3 = (2,"bj","come")
//创建tt3的迭代器
val tupleIte = tt3.productIterator
while(tupleIte.hasNext) print(tupleIte.next + "\t")
//反转,只针对二元组
val swap = tt2.swap
//toString
println(tt3.toString())
Scala Trait(特征)相当于java中抽象类和接口的集合体,不只是具备接口的特征,还可以定义属性和方法的实现。一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。
继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。并且trait中不可以传参数。
//定义一个trait
trait Read {
val readType = "Read"
val gender = "m"
def read(name:String){
println(name+" is reading")
}
}
//继承上面的trait
class Person() extends Read{
override val gender = "f"
}
模式匹配类似于java的switch case。Scala的模式匹配不仅可以匹配值还可以匹配类型、从上到下顺序匹配,如果匹配到则不再往下匹配、都匹配不上时,会匹配到case _ ,相当于default、match 的最外面的”{ }”可以去掉看成一个语句。
def match_test(m:Any) = {
m match {
case 1 => println("nihao")
case m:Int => println("Int")
case _ => println("default")
}
}
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
样例类默认帮你实现了toString,equals,copy和hashCode等方法。
样例类可以new, 也可以不用new。
case class Person1(name:String,age:Int)
object Lesson_CaseClass {
def main(args: Array[String]): Unit = {
val p = new Person1("zhangsan",10)
}
}