一、函数高级应用
1、函数传名调用
传值调用:先计算参数表达式的值,在传到函数内部
传名调用:先将为计算的参数传入函数内部,等到需要再去计算
//传值调用
def main(args: Array[String]): Unit = {
fun2(fun1())
}
def fun1 ():String={
println("调用第一个函数")
return "第一个函数的返回值"
}
def fun2 (t:String):Unit={
println("调用之前")
println(t)
println("调用之后")
}
输出: 调用第一个函数
调用之前
第一个函数的返回值
调用之后
//传名调用
def main(args: Array[String]): Unit = {
fun2(fun1())
}
def fun1 ():String={
println("调用第一个函数")
return "第一个函数的返回值"
}
def fun2 (t: => String):Unit={
println("调用之前")
println(t)
println("调用之后")
}
输出: 调用之前
调用第一个函数
第一个函数的返回值
调用之后
2、指定函数参数名调用
//指定函数参数名调用
def fun2(a:Int,b:Int):Unit={
println(a)
println(b)
}
def main(args: Array[String]): Unit = {
fun2(b=11,a=55)
}
3、可变参数的函数
//可变参数的函数
def fun3(paras:String*):Unit= {
for (temp <- paras) {
println(temp)
}
}
def main(args: Array[String]): Unit = {
fun3("11","2","fff","hgh")
}
4、默认参数值的函数
//默认参数值的参数
def fun4(a:Int=2,b:Int=6):Int={
return a*b
}
def main(args: Array[String]): Unit = {
println(fun4())
println(fun4(1))
println(fun4(8,9))
}
5、递归函数
//递归函数
def fun5(i:Int):Int={
if (i==1){
return 1
}else{
return i*fun5(i-1)
}
}
def main(args: Array[String]): Unit = {
println(fun5(5))
}
6、高阶函数
//高阶函数
def fun6(t: =>String):Unit={
println("函数二开始")
println("t")
println("函数二结束")
}
def temp ():String={
println("调用函数一")
return "res";
}
def main(args: Array[String]): Unit = {
fun6(temp())
}
7、内嵌函数
//内嵌函数
def fun7(a:String):Unit={
def function7(b:String):Unit={
println(b)
}
function7(a)
}
def main(args: Array[String]): Unit = {
fun7("aaa")
}
8、匿名函数
//匿名函数
var fun8 = (x:Int) => x+1
def main(args: Array[String]): Unit = {
println(fun8(4))
}
9、偏应用函数
不需要提供函数需要的所有参数,只需要提供部分,或不
提供所需参数
实现方法:绑定函数的一部分参数,非绑定部分用”_”代
替,从而形成偏应用函数去使用
//偏应用函数
def fun9 (name:String,msg:String)={
println(name + "--"+msg)
}
def main(args: Array[String]): Unit = {
var nnn = "张三"
var tempfun = fun9(nnn,_:String)
tempfun("上午好")
tempfun("中午好")
tempfun("下午好")
}
10、函数柯里化
//函数柯里化
//正常写法
def add (a:Int,b:Int): Int ={
return a+b
}
//柯里化1
def add1 (a:Int):Int => Int ={
( b : Int)=>a+b
}
//柯里化2
def add2 (a:Int)(b:Int)=a+b
def main(args: Array[String]): Unit = {
var add11 = add1(3)
var add22 = add2(3)(_)
println(add11(4))
println(add22(4))
}
二、集合collection
1、概念说明
- 与Java中的类似,分为可变集合和不可变集合
- 常用集合:Scala list、Scala Map、Scala Set、Scala 元组、Scala option、Scala Iterator迭代器
2、Scala List(列表)
- 类似数组,要求所有元素类型相同
- 是不可变集合,定了就无法改变
- 列表具有递归定义的性质,可以嵌套定义,这是与数组最大的不一样。
- Seq是一个特征,List是一个实现。也可以使用Seq
常用操作://列表初始化
//字符串列表
val list1:List[String] = List("11","dd","ggg")
val list11 = "python" :: ("c++" :: Nil)
val list111 = "112" :: ("aaa" :: Nil)
//整型列表
val list2:List[Int] = List(1,2,3,4)
//空列表
val list3:List[Nothing] = List()
//二维列表
val list4:List[List[String]] = List(List("22"),List("2"))
- head 返回列表第一个元素
- tail 返回除第一个元素之外的其他元素
- isEmpty 在列表为空时返回true
- ::: 或者 List.::: 或者 List.concat 方法连接两个或多个列表
- List.reverse 用于将列表的顺序反转
3、Scala Set(集合)
- 没有重复的对象的集合,所有元素都是唯一的
- Set分为可变和不可变集合两种
- 默认使用不可变集合,完整类路径为:scala.collection.immutable.Set
- 若要引用可变集合类型,则类路径为:scala.collection.mutable.Set
//可变集合
var set2 = scala.collection.mutable.Set (5,6,8,9,0,3)
println(set2)
println(set2.getClass.getName)
set2.add(1)
println(set2)
set2.remove(0)
println(set2)
//转换为不可变
val set3 = set2.toSet
println(set3.getClass.getName)
常用操作:
- head 返回第一个值
- tail 返回除第一个外所有值
- isEmpty 在集合为空时返回true
- 使用 ++ 或者 Set.++来连接两个集合
- set.min set.max 来查找最小和最大元素
- set.&或者set.intersect 查看两个元素的交集
4、Scala Map(映射)
- 一种可迭代的键值对结构
- 所有值都是通过键来获取的。键是唯一的
- 分为可变和不可变
默认是不可变,可变需要使用import scala.collection.mutable.Map 类
// Scala Map
//不可变的空Map
var map1 : Map [String,Int] = Map()
//不可变初始化
var map2 = Map("这是1"-> 1 ,"这是2"-> 2 ,"这是3"-> 3 ,"这是4"-> 4 ,"这是5"-> 5 )
//向不可变中添加值
map1 += ("zzz"->8)
map2+= ("aaaa"->9)
println(map1)
println(map2)
//初始化可变Map
val map3 = scala.collection.mutable.Map("这是1"-> 1 ,"这是2"-> 2 ,"这是3"-> 3 ,"这是4"-> 4)
map3 .put("zzz",8)
println(map3)
关于Map可变与不可变的总结:
不可变:取决于val 和 var, val只能读 var可以读写
可变:不论val 和 var 都可以读写
常用操作:
- keys:返回Map所有的键
- values:返回所有的值
- isEmpty:在Map为空时返回true
- 使用++或者Map.++连接两个集合,合并时会移除重复的K
- 使用Map.contains,查看Map中是否存在K
5、元组
- 与列表相似,元组时不可变的
- 与列表不同的是元组可以包含不同类型的元素
元组是通过()来定义的
//Scala元组
var yuanzu1 = (1,2,4,"aa","44")
var yuanzu2 = new Tuple4(1,1,1,2)
//元组的访问通过下标,第一个元素为 _1,以此类推
println(yuanzu1._1)
//元组的遍历
yuanzu1.productIterator.foreach(i=>println(i))
6、Option
表示有可能包含值的容器,也可能不包含值,主要表示一个值是可选的
- Option【T】是一个可选值为T的容器,如果存在内容,则为Some【T】,否则就是None
- 方法getOrElse()来确定是否包含某个值,如果包含就返回,不包含就返回默认值
isEmpty()来检测元组中的元素是否为None
//Scala Option
//先定义一个Map对象
var map = Map("java"->"java程序设计","c"->"c程序设计","js"->"js程序设计","py"->"py程序设计")
var option:Option[String] = map.get("java")
var option1 = None
println(option)
println(option.isEmpty)
println(option.getOrElse("c","bucunzai"))
println(option1.getOrElse("bucunzai"))
总结:getOrElse()方法在Map和Option都可以使用。
7、Iterator 迭代器
它不是一个集合,它是一个访问集合的方法
- 基本操作时hasnext和next
- size、length 返回迭代器对应集合的长度
- max返回集合最大值,min返回最小值
- hasNext()判断集合是否还有下一个元素
- Next()返回下一个元素
注意:迭代器只能调用一次
def main(args: Array[String]): Unit = {
//Iterator迭代器
var it1 = Iterator("11",2,"java","c")
var it2 = Iterator(2,4,5,7,8)
var it3 = Iterator(2,4,5,7,8)
var it4 = Iterator("java","c++","scala")
var it5 = Iterator("java","c++","scala")
while (it1.hasNext){
println(it1.next())
}
println("------------------------")
println(it4.length)
println(it1.size)
println(it4.max)
println(it5.min)
}
三、类和对象
大体与Java很相似
Scala的类和对象特点:一个Scala源文件中可以有多个类
- 类的访问修饰符默认public,不需要指定
类本身不能作为程序入口,必须通过定义Object对象,该对象的main方法作为程序入口
1、基础使用
```scala class student(onename:String,oneage:Int){ var name:String = onename var age:Int = oneage
def func(msg:String): String ={ return msg } }
object TestPersion{ def main(args: Array[String]): Unit = { var stu = new student(“张三”,21) println(stu.name) println(stu.age) println(stu.func(“aaaaaa”)) } }
<a name="oRpT8"></a>
## 2、类的继承
1. scala继承一个类和Java相似,也有一些不同
1. 重写一个非抽象方法必须加overwrite
1. 只有主类的构造函数才能向基类放参数
<a name="FjZ2n"></a>
## 3、单例模式
1. 在Scala中没有static
1. Scala使用object关键字解决单例模式,object和class的区别是object不能带参数
简单版单例模式
```scala
object ChineseSingleton {
var skinColor = "Yellow"
var country = "中国人"
}
object TestSingleton {
def main(args: Array[String]): Unit =
{
println(ChineseSingleton.skinColor)
println(ChineseSingleton.country)
ChineseSingleton.skinColor = "黄色";
println(ChineseSingleton.skinColor) }
}
Scala版本单例模式
- 伴生对象:除了定义的类之外,还要定义一个同名object对象
- 必须在同一个源文件里定义
- 类和他的伴生对象可以互相访问其私有成员 ```scala /**
- 定义伴生类 / class TaskManager private (oneName: String) { //将构造方法传入的局部变量,传递成类的成员变量,方便后续在外部使用使用 var name: String = oneName //定义成员方法 def getName(): String = { return name; } } /*
- 定义伴生对象 / object TaskManager { var taskManager = new TaskManager(“windows 任务管理 器”); def getSingletonInstance(): TaskManager = { return taskManager } } /*
- 测试单例模式
*/
object TestSingleton {
def main(args: Array[String]): Unit = {
var singleton =
TaskManager.getSingletonInstance();
println(singleton.getName());
} }
```
4、特征 trait
- 相当于Java的接口和抽象类二合一
- 支持多继承
- 用关键字trait定义关键字 ```scala /**
- 定义核心计算特征 / trait CalcuteCoreTrait { def add(a: Int, b: Int): Int = a + b def minus(a: Int, b: Int): Int = a - b def factorial(n: Int): Int } class TLCalculator(oneName: String) extends CalcuteCoreTrait { var name = oneName def factorial(n: Int): Int = { if (n <= 1) { return 1 } else { return n factorial(n - 1) } } } object TestTrait { def main(args: Array[String]): Unit = { var tl:CalcuteCoreTrait=new TLCalculator(“晨光计 算器”) var a=3 var b=4 println(“a+b=”+tl.add(a, b)) println(“a-b=”+tl.minus(a, b)) println(“b!=”+tl.factorial(b)) } } ```