数据类型:
非引用数据类型:父类型均为AnyVal
七种数值类型Byte、Char、Short、Int、Long、Float 和 Double
非数值类型:Boolean、Unit 类型.
引用数据类型:父类型均为AnyRef
变量
Var|Val 变量名[: 数据类型] = 变量值
Var 定义变量 var name: String = “Scala”
Var name = “Scala”(当不指定数据类型时,会根据变量值进行推测,由第一次赋值类型决定改变量的数据类型)
Val 定义常量
字符串的格式化输出
val name = “zhangsan” val sex = “male”
普通输出: println(“name:” + name + “ sex:” + sex) 输出name:zhangsan sex:male
println(“name:” + name, “ sex:” + sex) 输出(name:zhangsan, sex:male)
f插值器: 作用:1.在字符串中去变量值;2.对变量进行格式化(使用格式化符号%d, %s, %f等)
println(f”姓名$name%s, 性别$sex%s”) 输出 姓名zhangsan, 性别male (该输出有换行)
printf(“姓名%s, 性别%s”, name, sex) (该输出没有换行)
s插值器: (常用)可以直接在处理字符串时直接使用变量
println(s”name=$name, sex=$sex”) 输出name=zhangsan, sex=male
条件表达式
if...else if...else
循环语句/yield关键字
for(i <- 表达式/数组/集合){}
通过角标获取数组中的元素
for(i <- 0 to 5){} //0 to 5 会生成一个范围集合Range(0,1,2,3,4,5)
for(i <- 0 until 5){} //0 until 5 会生成一个范围及格Range(0,1,2,3,4)
也可以动态获取数组的长度作为角标
for(i <- 0 until array.length){} 或者for(i <- 0 until array.size){}
也可以在for循环中增加守卫(条件)
例如:获取数组中的偶数
for(i <- 0 until array if array(i) % 2 == 0){}
等同于:
for(i=0; i <array.length;i++){
If(array(i) % 2 == 0){
println(array(i));
}
}
Scala中的for循环嵌套
for(i <- 1 to 3; j <- 1 to 3 if i != j) {
println ((10 * i + j) + "")
}
上述代码逻辑等同于java中的如下代码
for(i = 1 ; i <= 3 ; i++) {
for(j = 1; j <= 3; j++) {
if(i != j) {
println ((10 * i + j) + "")
}
}
}
yield关键字:将满足条件的结果集进行封装
for(e <- array if e % 2 == 0) yield e
val array = Array(1, 2, 3, 4, 5, 6)
//for循环用法一:
println("\n===========for循环的用法一=================")
for (ele <- array) { //类似于Java的增强for循环
println(ele)
}
println("\n==============for循环的用法二==============")
//for循环用法二:
for (ele <- 0 to 5) {
//将0到5依次赋值给ele 区间左右都是闭
println(array(ele))
}
println("\n==============for循环的用法三==============")
//for循环用法三:
for (ele <- 0 until 6) { //区间左闭右开
println(array(ele))
}
println("\n=============使用角标动态获取数组中的值===============")
//也可以用角标的方法动态获取数组的长度
for (ele <- 0 until array.length) {
println(array(ele))
}
println("\n============================")
for (ele <- 0 until array.size) {
println(array(ele))
}
println("\n===========打印数组中的偶数=================")
//普通方式
for (ele <- 0 until array.size) {
if (array(ele) % 2 == 0) {
println(array(ele))
}
}
println("\n===========打印数组中的偶数=================")
//在for表达式中使用守卫
for (ele <- 0 until array.length if array(ele) % 2 == 0) {
println(array(ele))
}
println("\n===========打印数组中的偶数=================")
for (ele <- array if ele % 2 == 0) {
println(ele)
}
println("\n============================")
for (i <- 1 to 3;j <- 1 to 3 if i != j) {
println((10 * i + j) + "")
}
println("\n===========yield关键字=================")
//yield用于封装满足条件的结果集
val newArray = for (ele <- array if ele % 2 == 0) yield ele
println(newArray)
操作符重载成方法
Scala中+-*/%等操作符的作用与java相同,位操作符&|^>><<也一样
但是在Scala中这些操作符实际上都是方法。
例如: a + b 是 a.+(b) 的简写
方法的定义和调用
定义方法的格式:def methodName(参数列表)[: 返回值类型] = {}
注意:
当无参方法调用时:
如果方法定义时候参数列表没有() 调用时不能加()
如果方法定义时候参数列表有(),调用时候()可以省略, 也可以不省略
方法可以转换为函数:
函数式编程中函数是第一位的,在Scala中,方法和函数有所不同
最明显的不同:方法不能赋值给变量,函数可以赋值给变量
函数的定义
函数的标志:=>
函数定义方式一:
函数定义方式二:
函数的传值调用与传名调用
通常,函数的参数就是传值参数;也就是说,参数的值在传递给函数之前确定
传名调用:也就是将一个方法或者函数作为函数的参数(方法作为参数会转化为函数)
/**
* scala的
* 传名调用(call-by-name)
* 传值调用(call-by-value)
*/
object ScalaCallName s extends App{
def currentTime(): Long ={
println ("打印系统当前时间, 单位纳秒")
System. nanoTime ()
}
/**
* 该方法的参数为一个无参的函数, 并且函数的返回值为 Long
*/
def delayed(f: => Long): Unit = {
println ("delayed ===============")
println ("time=" + f)
}
def delayed1(time: Long) = {
println ("delayed1===============")
println ("time1= " + time)
}
// 调用方式一
delayed ( currentTime )
println ( "------------ 华丽丽的分割线 ----------")
// 调用方式二
val time = currentTime ()
delayed1 ( time )
}
可变参数函数:
// 定义一个可变参数的方法
def methodManyParams(a: String*) = {
for (p <- a) {
println (p)
}
}
// 调用
methodManyParams ("中华", "人民", "共和国")
默认值参数函数:
// 带默认值的参数列表
def add(a: Int = 1, b: Int = 7): Int = {
println (s"a + b = ${a + b}" )
a + b
}
// 调用
add (2) // 带有默认值 a 的参数, 调用时可以不传
add (b=9, a=2) // 调用时, 可以指定具体的参数值
add (b=18) // 调用如果执行修改某一个具体的参数值的话, 可以指定参数名称
高阶函数:
// 高阶函数: 将其他函数作为参数或其结果是函数的函数
// 定义一个方法, 参数为带一个整型参数返回值为整型的函数 f 和 一个整型参数 v, 返
回值为一个函数
def apply(f: Int => String, v: Int) = f(v)
// 定义一个方法, 参数为一个整型参数, 返回值为 String
def layout(x: Int) = "[" + x.toString() + "]"
// 调用
println ( apply ( layout , 10))
部分参数应用函数:
将预期的参数全部传递,表示已经完全的应用。
传递其中的几个并不是全部的参数,那么则会返回部分应用函数。
部分参数应用函数,因为传递部分参数,增加了适用性,减少了通用性
// 定义个输出的方法, 参数为 date, message
def log(date: Date, message: String) = {
println ( s"$date, $message")
}
val date = new java.util.Date()
// 调用 log 的时候, 传递了一个具体的时间参数, message 为待定参数
// logBoundDate 成了一个新的函数, 只有 log 的部分参数(message)
val logBoundDate : (String) => Unit = log ( date , _: String)
// 调用 logBoundDate 的时候, 只需要传递待传的 message 参数即可
logBoundDate ("hi jerry")
logBoundDate ("hi 猴哥")
柯里化(Currying)
柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。
柯里化函数的特征:参数列表出现了多个括弧
// 我们看下这个方法的定义, 求 2 个数的和
def add(x: Int, y: Int) = x + y
// 那么我们应用的时候,应该是这样用:add(1,2)
// 现在我们把这个函数变一下形:
def add(x:Int)(y:Int) = x + y
// 那么我们应用的时候,应该是这样用:add(1)(2),最后结果都一样是 3,这种方式(过
程)就叫柯里化。经过柯里化之后,函数的通用性有所降低(写死了参数必然导致了不同业务场景下的通用性降低),但是适用性有所提高(适用了特定场景)。
// 分析下其演变过程
def add(x: Int) = (y: Int) => x + y
// (y: Int) => x + y 为一个匿名函数, 也就意味着 add 方法的返回值为一个匿名函数
// 那么现在的调用过程为
val result = add(2)
val sum1 = result (3)
val sum2 = result (8)
偏函数
被包在花括号内没有 match 的一组 case 语句是一个偏函数,它是 PartialFunction[A, B]的一个实例,A 代表参数类型,B 代表返回类型,常用作输入模式匹配。
object PartialFuncDemo {
def func1: PartialFunction[String, Int] = {
case "one" => 1
case "two" => 2
case _ => -1
}
def func2(num: String) : Int = num match {
case "one" => 1
case "two" => 2
case _ => -1
}
def main(args: Array[String]) {
println ( func1 ( "one"))
println ( func2 ( "one"))
}
}