Scala学习笔记(1)
Scala的基础语法
1、变量类型
AnyVal
共有9种:
Byte、Short、Int、Long、Float、Double、Char、Boolean、Unit(void)
AnyRef
String....
2、val和var的区别
scala有两种定义变量的方式:val和var
val定义好变量后,无法更改变量的值,类似于java中的final
var定义的变量,可以多次修改。
unit表示无值,和其他语言中的void相同。
var 变量名称:变量类型 = 变量具体值
在不指定变量数据类型的情况下,scala会自动对其类型推导。
推荐使用val
3、循环
基本语法结构:for( 变量 <- 表达式) ,eg:for( i<- 0.until(s.length) )、for(ch <- "Hello" )
高级for循环:以变量 <- 表达式的形式提供多个生成器,用分号隔开它们,每个生成器都可以带一个守卫:以if开头的Boolean表达式。
for( i < 1 to 3 ;j <- 1 to 3 ) print( (10* i +j ) + " ")
//打印:11 12 13 21 22 23 31 32 33 ,每个i都会经历j<-1 to 3
for( i < 1 to 3 ; from = 4 -i ;j <- from to 3 ) print( (10* i +j ) + " ")
//打印: 13 22 23 31 32 33 ,每个i都会经历from = 4 -i ;每个form都会经过j <- from to 3
for( i < 1 to 3 ;j <- 1 to 3 if i != j) print( (10* i +j ) + " ") //带守卫,注守卫没有分号
//打印: 12 13 21 23 31 33 ,每个i都会经历j <- 1 to 3 if i != j
4、break
scala中没有break语句,但是Breaks对象提供了break方法。
引入Breaks包:
import scala.util.control.Breaks._
var a = 9 breakable( while(true){ println(a) a = a - 1 if(a == 5) break() } )
5、yield的用法
yield 关键字的简短总结:
针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
当循环结束后, 会返回所有 yield 的值组成的集合.
返回集合的类型与被遍历的集合类型是一致的.
val array = Array(1,2,3,4,5,6) val result = for(i <- array if i %2 == 0) yield i println(result.toBuffer)
遍历文件:
import java.io.File import scala.io.Source /** * Created by fred on 2018/7/1. */ object YieldDemo{ val files = (new File("/Users/fred/Desktop/Data/scala_test")).listFiles() // for(file <- files){ // println(file) // } def fileLines(file:java.io.File) ={ Source.fromFile(file).getLines.toList } def main(args: Array[String]): Unit = { val result = for{ file <- files if file.getName.endsWith(".txt") line <- fileLines(file) trimmedLine = line.trim if trimmedLine.matches(".*scala.*") } yield trimmedLine.length result.foreach(println) } }
6、方法和函数
方法:方法作用于对象,是对象的行为。
定义方法的基本格式是:def 方法名称(参数列表):返回值 = 方法体
函数定义有两种方式:
(1)val 函数名称:(参数名称:参数类型...) => 业务运算逻辑
(2)val 函数名称:(参数类型...) => 返回值类型 = (参数) => 业务运算逻辑
scala中方法的返回值默认是方法体中的最后一行表达式 的值,当然也可以用return来执行返回值,但scala并不推荐这么做。
scala提供一些强大的功能:类型推断。在定义方法时,可以不显式 的制定方法的返回值,scala编译器可以根据函数体中的具体内容来推断方法的返回值类型。
/*不显示的指定返回值类型*/ def function01(a:Int, b:Int) = { a + b } /*显示的指定返回值类型*/ def function02(a:Int, b:Int):Int = { a + b }
需要注意的是,若使用return
来制定函数的返回值,次数scala的类型推断将会失效,必须显式执行返回值类型。
返回值类型:1)函数不是递归的就不需要指定返回类型,可以根据=符号右侧表达推断出来。2)如果方法使用了return,必须制定方法的返回值类型
/*不显示的指定返回值类型 *return时,若不指定返回值类型会编译出错 * */ def function01(a:Int, b:Int) = { return a + b } /*显示的指定返回值类型*/ def function02(a:Int, b:Int):Int = { return a + b }
/* 递归 */ def multiply(n:Int):Int = { if(n == 1) 1 else n * multiply(n - 1) }
当然,方法也可以没有返回值(返回值是Unit)。
默认参数和带名参数
在定义方法参数时,可以为某个参数指定默认值,带有默认值的参数在被调用时可以不为其传入实参。
def function03(left:String = "[", content:String, right:String = "]"): Unit ={ println(left + content + right) }
上面定义的方法中,参数left
和right
已经指定默认值,可以用下面的方式进行调用
function03(content = "hello")
这里有一点需要注意,当未被指定默认值的参数不是第一个参数时,参数名称不能省略
/*这样调用是不对的*/ function03("hello")
可变参数
当方法需要多个相同类型的参数时,可以用可变参数简化方法的定义
def sum(args:Int*){ var result = 0 for(arg <- args) result += arg println(result) }
函数的定义:
/** * 函数的定义有两种方式 */ /*匿名函数*/ (a: Int, b: Int) => a + b /*方式一 val 函数名称:(参数名称:参数类型...) => 业务运算逻辑 */ val f0 = (a: Int, b: Int) => a + b /* 方式二 val 函数名称:(参数类型...) => 返回值类型 = (参数) => 业务运算逻辑 */ val f1: (Int, Int) => Int = (a, b) => a + b
参数列表:对方法是可选的,对函数是必须的(函数参数列表可以为空)。函数本身可以作为方法的参数传入。
def callFunc(a: Int, b: Int) = { f0(a, b) } def callFunc_1(a: Int, b: Int, f: (Int, Int) => Int) = { f(a, b) }
在需要函数的地方可以提供一个方法(自动转换)
例如,高阶函数接收的是一个函数,但也可以传入一个方法,scala会将这个方法自动转义成函数。
def function04(x:Any) = println(x) val list = List[String]("a", "b", "c", "d") list.foreach(function04(_))