scala突击复习

Scala突击复习笔记

一、scala基础语法

1.变量和常量

​ val和var关键是声明变量使用(区分:val看做是Java中的final修饰的常量,不可改变。而var则可以看做变量,可变)。

(1).变量

​ 使用var修饰, 内容和引用都可以改变。

scala> var a = 10
a: Int = 10

scala> a= 20
a: Int = 20
(2).常量

​ val可以看做是Java中的final,不能修改其引用的地址, 但是可以修改其引用的对象的内部的其他值, 在实际开发中, 推荐使用val修饰, 如果使用var可能会出现修改值的问题, 因为在网络传输中, 会对变量进行序列化和反序列化, var修饰的变量可能会发生值的改变, 数据传输错误或不安全, 所以一般情况下推荐使用val。

scala> val b = 10
b: Int = 10

scala> b = 20
scala> b = 20
         ^
		error: reassignment to val
       
(3).lazy关键字

​ 用来修饰val时,不是立即为其创建空间,直到被调用时,才开辟内存空间

scala> lazy val c = 10
c: Int = <lazy>

scala> c
res0: Int = 10

2.常用的数据类型和Java对照

在这里插入图片描述

​ 在scala中, 一切都是类, 没有基础类型和包装类之分。基本数据类型: Byte Char Short Int Long Float Double Boolean, 初看之下和Java中的包装类很类似,但是这里需要注意和Java中的包装类使用完全不相同。scala中是不区分引用类型和基本类型的,所有都看做是对象, scala会自己负责基本数据类型和引用类型之间的转换。既然是对象,则本身会有方法,可以直接调用。

val a:String = 1.toString

3.运算符

​ scala的运算符和java的没有太大区别,但是没有++和–运算,可以用+=和-=代替。

4.流程控制

(1).条件判断语句

​ 使用和java的差不多,但是scala的分支语句有返回值,可以传回。若返回的数据类型不一致, 则取其父类Any。

val res:Any = if(a < 10) "字符串" else 100
//当a<10的时候,返回“字符串”这三个字给res,若其他情况则返回100这个数值给res
(2).循环语句

​ 和java一样,有do…while,while和for三种循环方式。使用相差不大,其中for的条件判断有些差异。scala的for循环条件判断不是java的(赋值,条件判断,条件运算)格式。而是直接指定循环区间,有to和until两种方式。区别在于until不包含最后一个值(含前不含后),而to包含最后一个值。

//to循环1到10
scala> for(i<-1 to 10){print (i+" ")}
1 2 3 4 5 6 7 8 9 10

//until循环1到10
scala> for(i<-1 until 10){print (i+" ")}
1 2 3 4 5 6 7 8 9

二、Scala方法和函数

​ 方法和函数的区别:

​ 方法:是类的一部分,是对象的一部分,和java类似,使用def关键字定义;

​ 函数:是一个对象,可以作为参数传给方法,使用val关键字定义。

1.方法的定义

(1).标准定义(return可写可不写,scala会自行推断。逻辑复杂建议不省略)
def 方法名(参数名:参数类型...):返回值类型 = {方法体}

//例如
def sum(a:Int, b:Int):Int = {
    a+b
}
(2).简化定义

​ 因为scala是自动推断脚本语言,所以方法中的返回值类型可以不写,编译器会根据方法体中的返回值自行推断。

//简化1:不写方法返回值
def 方法名(参数列表) = {方法体}
eg:def sum(a:Int, b:Int) = {println(a+b)}

//简化2:不写等号
def sum2(a:Int,b:Int){println(a+b)}

//没有参数,没有返回值
def sum3():Unit = {
println("求和")
} 

//但是若是递归函数,必须些返回类型
//递归: 实现斐波那契数列
def fab(n:Int):Int={
    if((n == 1) ||(n == 2)){
        1
    }
    else{
        fab(n-1)+fab(n-2)
    }
} 

3.常见的函数的定义方式(有一种通过new Function2的方式不记录)

(1).声明函数返回类型定义
val 函数名:((参数类型...)=>返回值类型) = {(参数名...)=>(方法体)} 

//举例
scala> val diff:((Int, Int)=>Int)={(x,y)=>(x-y)}
diff: (Int, Int) => Int = <function2>

scala> diff(3,2)
res21: Int = 1
(2).不声明函数返回类型定义
val 函数名=(参数名:参数类型...) => {方法体}

//举例
val add = (a:Int, b:Int)=>{a+b}
(3).参数名不写,使用‘_’代替
scala> val f1:(Int,Int)=>Int=(_+_)
f1: (Int, Int) => Int = <function2>

scala> f1(2,5)
res1: Int = 7

4.高阶函数

(1).参数是另一个函数
val f1 = (f:(Int, Int)=>Int) => {
    val a = f(2,3)
    println(a)
}

val f2:((Int, Int) => Int) = {(x,y)=>(x+y)}

scala> f1(f2)
5
(2).函数作为返回值

​ 需求:根据参数为true或者false来调用转换大小写的函数

​ 1.定义转换大写的函数f1

val f1:(String)=>String = {(x)=>{x.toUpperCase}}

​ 2.定义转换小写的函数f2

val f2:(String)=>String = {(x)=>{x.toLowerCase}}

​ 3.令f1或f2作为函数f3的返回值(这里传入true)

val f3:(Boolean)=>((String)=>String) = {(x)=>{
    	if(x == true){
            f1
        }else{
            f2
        }
	}
}

​ 4.调用函数

val f4 = f3(true)
f4("helloworld")
//输出
res3: String = HELLOWORLD

5.数组

(1).定长数组

​ 长度不变的数组,实用scala包中的Array类。

定长数组的定义:

//第一种,通过new的方式定义,默认数组中元素初始值是0
val arrray = new Array[Int](5)

//第二种,直接给定初始值
val array = Array(1,2,3,4,5)

定长数组的操作:

​ 1.打印定长数组

//如果是直接打印,则打印出来的是数组对象的hashCode
println(array)
[I@6c07ad6b
 
//需要转化为缓冲数组方能正常查看其中内容
array.toBuffer
scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)

​ 其余插入,修改数据的操作和java一样。

(2).变长数组

数组定义:

//第一种,使用new对象的方式
import scala.collection.mutable.ArrayBuffer
val array = new ArrayBuffer[Int](4)

//第二种,直接赋值数组
val array = ArrayBuffer(1,2,3,4)

变长数组的操作:

//在末尾添加元素+=
val array = ArrayBuffer(1,2,3)
array += 10

res17: array.type = ArrayBuffer(1, 2, 3, 10)

//在末尾添加多个元素,用()括起来
val array = ArrayBuffer(1,2)
array += (3,4)

res18: array.type = ArrayBuffer(1, 2, 3, 4)

//在尾端添加另一个数组,++=
val array1 = ArrayBuffer(1,2,3)
val array2 = ArrayBuffer(4,5,6)
array1 ++= array2

res24: array1.type = ArrayBuffer(1, 2, 3, 4, 5, 6)

//移除最后N个元素,trimEnd(n)
val array = ArrayBuffer(1,2,3,4,5,6)
array.trimEnd(3)

res27: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

//缓冲数组转成不可变数组,toArray()
(3).遍历数组

​ 基本用法和java相同,这里仅仅记录较为特殊的不使用下标直接遍历的方式。

val array = Array(a,b,c,d)

for(i <- array){
    println(i)
}
a
b
c
d
(4).数组常用算法

sum求和

max(min)求最大最小值

sorted从小到大排序

sortWith((x,y)=>{x>y})或者sortWith((x,y)=>{x<y})冒泡排序,可以指定正序排序或者倒序排序

reverse翻转

6.map映射

​ Scala提供两种类型的映射:一类是值可以改变的映射,位于scala.collection.immutable.Map包,另一类是值不可以改变的映射,位于scala.collection.mutable.Map包。

(1).构造值可变映射
//第一种方式,在构造时赋值
val map = scala.collection.mutable.Map("001"->"张三", "002"->"王五")

//第二种方式,在构造时不赋值,但是需要指定kv对泛型
val map = new scala.collection.mutable.HashMap[String, String]

修改或获取映射中的值

//1.获取映射的值
map("001")

res58: String = 张三

//2.更改映射中的值
map("001") = "二麻子"
map("001")

res60: String = 二麻子

//3.添加数据
map += ("003"->"大傻子")

//4.删除数据
map-=map("001")
(2).构造值不可变映射
//第一种方式,在构造时赋值
val map = Map("001"->"张三", "002"->"王五")

//第二种方式,在构造时不赋值,但是需要指定kv对泛型
val map = new scala.collention.immutable.HashMap[String, String]
(3).映射遍历的三种方式
//第一种
for((x,y) <- map){
    println(x+"--->"+y)
}

001--->张三
002--->王五

//第二种
for(x <- map){
    println(x)
}

(001,张三)
(002,王五)

//第三种
val a = map.keySet
for(k <- a){
    println(k)
}

001
002

for(k <-a){
    println(map(k))
}

张三
王五

7.元组Tuple

​ 目前Scala支持的最大元组长度为22(可以理解为一个可以存储不同数据类型的数据结构),对于更长的元组可以使用集合或者扩展元组。

//直接创建
val t1 = (1,"张三",3.14)  //这种创建方式只可以用_1,_2,_3来访问对应位置的元素
val t2,(a,b,c) = (1,"张三",3.14)	//这种创建方式可以通过别名abc来访问元素

//通过new来创建元组,这样创建的元组也只可以用_1,_2,_3......来访问元素
val t3 = new Tuple2(1, 3.14)
val t4 = new Tuole3(1,"张三",3.14)

元组遍历:

t2.productIterator.foreach(x=>println(x))

1
"张三"
3.14

8.集合(List,Set)

​ 大致与java相同,要区分可变集合(ListBuffer)和不可变集合。对于不可变集合,每一次变化都是生成新对象覆盖了原对象。

9.Iterable常用方法

​ Iterable是所有集合的父类,所以其方法对所有集合都适用。

//sum,max,min求集合中最大最小值和求和

//count按照自定义规则计数,示例为统计list1中所有偶数个数,返回一个整型
list1.count(x=>{x%2==0})

//filter过滤(可以理解为按规则筛选出符合的数据),示例为筛选出list1中所有的偶数,返回一个集合
list1.filter(x=>{x%2==0})

//flatten扁平化处理,若有一个集合中的元素是多个集合,则将里面的集合元素全部拆解,合并为一个大集合
val list1 = List(1,2)
val list2 = List(3,4)
val list3 = List(5,6)
val list4 = List(list1,list2,list3)
//list4: List[List[Int]] = List(List(1,2), List(3,4), List(5,6))
val list = list4.flatten
//list: List[Int] = List(1,2,3,4,5,6)

//diff 差集,intersect 交集, union并集。这三个方法返回集合数据类型。

//map遍历集合中元素,对每个元素作出自定义操作,返回一个集合类型
val list = List(1,2,3,4)
val list2 = list.map(x=>{x*2})
//list2: List[Int] = List(2,4,6,8)

//flatMap扁平化遍历集合。先将集合中的每一个元素遍历出来,再对总集合做flatten扁平化。
val list1 = List(1,1,1)
val list2 = List(2,2,2)
val list3 = List(3,3,3)
val list = List(list1,list2,list3)
val list4 = list.flatMap(x=>x.map(y=>y*2)) //第一步先将各个子集合取出到x中,第二步遍历x中各个元素到y中乘以2,得到List((2,2,2),(4,4,4),(6,6,6))这样的集合,第三步对这个集合做扁平化。
//list4: List[Int] = List(2,2,2,4,4,4,6,6,6)

//zip拉链操作。对两个集合为位置相同的元素做合并为元组的操作,若一方有,一方没有的元素舍弃。最后返回一个元组集合。
val list1 = List(1,2,3)
val list2 = List(2,4)
val list1.zip(list2) //又可以写为 list1 zip list2
//res9:List[(Int,Int)] = List((1,2), (2,4))
val list2.zip(list2)
//res10:List[(Int,Int)] = List((2,1), (4,2))

//forall对整个集合进行条件检查,返回布尔值。遍历集合所有元素,一但有一个元素不满足检查条件,返回false。若都满足则返回true
val list = List(2,3,4,9)
list.forall(x=>x<6) //false  因为9比6大
list.forall(x=>x<100) //true

//partition对集合进行分组,返回集合元组,将相同分组条件的元素放到同一个子集合中。
val list = List(2,3,45,5,6)
list.partition(x=>(x%2==0))
//res11:(List[Int], List[Int]) = (List(2,6), List(3,45,5))

//reduce聚合,按照规则对集合中各个元素做聚合
val list = List(2,3,4)
list.reduce((x,y)=>{x+y}) //x一开始代表第一个元素,后面代表每一次计算后的结果,y则代表下一个元素
//res12:Int = 9

//groupBy分组函数。返回一个map类型集合,主键是分组条件的返回值,键值是符合的数据集合
val list = List(1,2,3,4,5,6,7,8,9,10)
list.groupBy(x=>{x%2==0})
//res12:Map[Boolean, List[Int]] = hashMap(false->List(1,3,5,7,9), true->List(2,4,6,8,10))

//grouped分组函数。给定一个长度,将原集合分为N个符合这个长度的子集合。若剩余元素不满足该长度,则最后那个集合仅仅保存剩余元素。
val list = List(2,3,45,5,6)
list.grouped(2).toList
//res149: List[List[Int]] = List(List(2, 3), List(45, 5), List(6))

10.面向对象编程

(1).创建类

​ 在Scala中有两种类,描述类class和执行类object。scala中的类不需要使用public修饰,一个文件中可以存在多个类,若没有提供构造方法,系统会提供默认的无参构造方法。

​ 对于class可以理解为java中用来生成对象的类,而object则是具有执行能力,例如main方法所在的类。

class Student {
  /**
    * 定义属性, 需要给定一个初始值
    * var修饰的属性相当于自带的get/set方法
    * val修饰的属性相当于只有get方法, 没有set方法---只读
    * _ 表示一个占位符, 可以作为初始化使用, 需要注意的是:
    * 若使用下划线作为初始值, 必须声明数据类型
    * _ 相当于给当前变量进行初始值赋值, 数值类型--> 0  引用数据类型 ---> null
    * 引用类型在使用时需要注意空指针
    */
  var name: String = _
  var age: Int = _
  var gender: String = _
  //var add = _  不能这么使用, 无法确定数据类型
  //val add:String = _ 也不能这么使用, val相当于final, 无法进行再次赋值, 在这里禁止使用下划线
  val add = "育新花园"
}

object Test {
  def main(args: Array[String]): Unit = {
    //创建对象 若创建对象没有构造方法, 使用的是默认构造, 所以可以省略小括号
    val stu = new Student
    //调用属性
    println(stu.name)
    println(stu.age)
    println(stu.add)

    //调用属性, 赋值, val修饰的属性不能进行再次赋值
    stu.gender = "男"
    println(stu.gender)
  }
}

(2).构造方法

在类后面添加()完成

  1. 一个类只能有一个主构造方法,可以有多个辅助构造方法(相当于java中可以重载多个构造方法,用于不同参数(参数数量不同,类型不同)等情况)。
  2. 若类中提供了构造方法,可以省略书写属性,在构造方法中提供了这些形参名,其实就是类的属性,我们只需要提供修饰即可对外访问。
  3. 不使用修饰之前,这些形参只能够在类中使用。
  4. 在使用val和var修饰之后,这些形参就可以在外部使用。
  5. 在构造的时候,可以给属性一个默认值。
class Person(val name: String, val age: Int, val faceValue: Int = 50) {

  var gender: String = _

  //没有var或者val修饰的时候, 可以在类的内部进行调用
  def show() = {
    println(name)
  }

  //提供辅助构造器
  def this(name: String, age: Int, faceValue: Int, gender: String) {
    //第一行必须调用主构造方法
    this(name, age, faceValue)
    this.gender = gender
  }
}

object PersonTest {
  def main(args: Array[String]): Unit = {
    //创建对象
    val p1 = new Person("laoliang", 37, 80)
    val p2 = new Person("laochen", 40)
    println(p2.faceValue)
    val p3 = new Person("laocao", 45, 2, "男")

  }
}

(3).伴生类和伴生对象不太常用

(4).特质和抽象类

特质:Thrait,相当于java中的接口,可以一个类可以实现多个特质。和java8后续版本一样,已经支持实现方法。

/**
  * scala中的特质, 除了关键字不一样外, 在当前代码中定义的和class类中定义的是完全一样的
  * 但是不能提供构造方法
  */
trait Fly {
  //声明有值的的属性
  val height = 2000
  //声明没有值的属性
  val speed:String
  //声明实现方法
  def fly():String = {
    "I can fly"
  }
  //声明一个没有实现的方法
  def play():String
}

抽象类:和java一样,使用abstract关键字。

/**
  * 企鹅类,抽象类, abstract修饰
  */
abstract  class QQ {
  //声明一个有值的字段
  val age = 5
  //声明一个无值的字段
  val name:String
  //声明实现的方法
  def show():String={
    "QQQQ"
  }
  //声明没有实现的方法
  def run():String

  var gender:String = "男"
}

继承特质和抽象类:

/**
  * 若在没有继承类的前提下, 直接使用extends 就可以继承特质
  * 若只是继承抽象类或其他类 也是使用extends
  * 若继承一个类实现一个特质, extends 类名 with 特质名
  * extends 类名 with 特质名 with 特知名 with 特知名......
  */
class Human extends QQ with Fly {
  override val name: String = "fly_name"

  override def run(): String = "跑"

  override val speed: String = "1000KM/H"

  override def play(): String = "斗地主"

  //重写
  override val age: Int = 20

  //被var修饰的属性不能被重写, 重写不会报错, 但是运行的时候会报错
  //override var gender:String="不详"
}

object Human{
  def main(args: Array[String]): Unit = {
    val h = new Human
    println(h.gender)
  }
}
(5).模式匹配(有一些类似java中的switch case)

1.标准模式:

数据 match{
    case 条件 => 输出
}

2.偏函数:

def show()={
    case 条件=>输出
}
  1. 模式匹配中, scala提供了一个类似于Java枚举的声明–>样例类
  2. Java中的switch-case需要使用break, 不然就会贯穿(从开始执行到结束)
  3. scala中的match-case没有break, 只要case满足就执行, 执行完就自动退出, 不会执行下一个case
  4. scala中使用_ 代替Java中的default, 最后的默认情况, 一定要放到最后
import scala.util.Random

object MatchCaseDemo {
  def main(args: Array[String]): Unit = {
    //创建一个数组
    val arr1 = Array("laoliang", "laocao", "laochen", "dazhao")
    //通过随机获取值进行匹配输出
    arr1(Random.nextInt(arr1.length)) match {
      case "laoliang" => println("laoliangjianggushi")
      case "laocao" => println("laocaolaocao")
      case "laochen" => println("laochenlaochen")
      case "dazhao" => println("heiheihei")
      case _ => println("默认")
    }

    println("-" * 50)
    val arr2 = Array("hello123", 1, 2, 3L, MatchCaseDemo)
    arr2(Random.nextInt(arr2.length)) match {
      //可以向写方法形参一样
      case x: Int => println("Int Type")
      case y: Double if (y < 0) => println("double Type")
      case MatchCaseDemo => {
        println("MatchCaseDemo Type")
      }
      case _ => println("default")

    }

    val arr3: Array[Int] = Array(2, 3, 45, 5, 6, 6)
    arr3 match {
      case Array(2, 3, x, y) => println("x+y=" + (x + y))
      case Array(2, 3, _*) => println("_* 代表后边所有值")
      case _ => println("default")
    }

    val tup1 = (1, 2, 5)
    tup1 match {
      case (1, 2, x) => println("x=" + x)
      case (x, y, z) => println("x+y+z: " + (x + y + z))
      case (_, x, 5) => println("下划线尽量不要使用, 可以使用变量接收")
      case _ => println("default")
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值