scala知识点总结

scala知识点总结

  • 什么是scala
    • 为什么要学习 Scala
    • scala 的特点
    • scala和java 有什么区别?
    • val 和var的区别?
    • scala的数据类型?
    • scala 运算符
    • scala块语句有什么特点?
    • scala break使用?
    • scala 函数和方法的区别?
    • scala 函数的参数?
    • scala 方法的几种写法?
    • scala 函数的写法
    • scala 闭包?
    • scala 柯里化?
    • scala 函数至简原则?
    • scala lazy?
    • Scala包的三大作用
    • scala中的三个默认导入包?
    • scala 访问修饰符,及作用域?
    • scala @BeanProperty 属性的特点?
    • scala var和val 修饰的对象有什么区别?
    • scala 的构造器?
    • scala 的继承?
    • scala的抽象类?
    • scala的内部类访问的方法?
    • scala object特点?
    • scala伴生类和伴生对象?
    • scala 的apply?
    • scala的类型检查和类型转换?
    • 使用 type 为数据类型设置别名
    • scala 数组?
      • 不可变数组
      • 可变数组
      • 不可变数组与可变数组的转换
      • 多维数组
    • scala的list
      • 不可变List
      • 可变ListBuffer
    • scala的map
      • 不可变Map
      • 可变Map
    • scala的set
      • 不可变Set
      • 不可变mutable.Set
    • scala的集合的head tail Nil?
    • scala的并行集合
    • scala的队列
    • 样例类的特点?
    • scala的模式匹配
    • scala的偏函数
    • scala的异常

什么是scala

Scala 是一门 以 Java 虚拟机(JVM)为运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言。

为什么要学习 Scala

Spark 是新一代内存级大数据计算框架,是大数据的重要内容

Spark 是使用 Scala 编写的,为了更好的学习Spark,需要掌握 Scala

Spark 的兴起,带动 Scala 语言的发展。

scala 的特点

函数是头等公民

OOP和函数式编程:Scala 是一门多范式的编程语言,Scala 支持面向对象和函数式编程。

Scala 源文件 .scala 会被编译成Java字节码文件 .class ,然后运行于JVM上,并且可以调用现有的Java类库,实现两种语言的无缝对接。

Scala语法简单:Scala单作为一门语言来看,非常的简洁高效。

Scala源于Java:Scala在设计时,参考Java的设计思想,也有自己独有的函数式编程语言的特点。

scala和java 有什么区别?

特点 JAVA SCALA
语法特点 相对Scala,代码冗余,但易读性高 相对于Java,语法简单,但是易读性差
声明变量 数据类型 变量名 = 值 var 变量名 = 值
声明常量 使用final关键字修饰 val 常量名 = 值
方法三要素 饰符 返回值类型 方法名(形参列表){方法体} def 方法名(形参: 类型): 返回值类型={方法体}

val 和var的区别?

语法:[关键字] 变量名 [: 变量类型] = 变量值

共同点:两者都需要 初始化,数据类型可以不指定,编译器会自动推导其类型。类型指定后,不能修改。

不同点:

​ val 是声明常量的关键字,声明的常量不能被再次赋值。

​ var 是声明变量的关键字,声明的变量可以被再次赋值。

scala的数据类型?

Scala中一切数据皆对象,都是Any的子类,类似于Java中的Object。

Scala中的数据类型分为两大类:AnyVal(数值类型)、AnyRef(引用类型)

  • AnyVal(值类型)
    • 整数类型:Byte、Short、Int、Long
    • 浮点类型:Float、Double
    • 字符类型:Char
    • 布尔类型:Boolean
    • Unit类型、Null类型和Nothing类型
  • AnyRef(引用类型)
    • Scala Collections(集合)
    • All java classes
    • Other Scala classes

scala 运算符

算术运算符:+(正号,加,字符串拼接)、-(负号,减)、*(乘)、/(除)、%(取余)

关系(比较)运算符:==(相等)、!=(不等)、<(小于)、>(大于)、<=(小于等于)、>=(大于等于)

逻辑运算符:&&(逻辑与)、||(逻辑或)、!(逻辑非)

赋值运算符:=(赋值运算符)、+=(相加后赋值)、-=(相减后赋值)、

​ *=(相乘后赋值)、/=(相除后赋值)、%=(取余后赋值)、

​ <<=(左移后赋值)、>>=(右移后赋值)、&=(按位与后赋值)

​ ^=(按位异或后赋值)、|=(按位或后赋值)

位运算符:&(按位与运算符)、|(按位或运算符)、^(按位异或运算符)、

​ ~(按位取反运算符)、<<(左移动运算符)、>>(右移动运算符)、

​ >>>(无符号右移)

scala块语句有什么特点?

组合几个表达式,使用 { } 包围起来,即代码块。

代码块中最后一个表达式的结果或一个值或者一个变量,即整个块的结果。

scala break使用?

// 导入break所在的包
import scala.util.control.Breaks._
object Demo {
  def main(args: Array[String]): Unit = {
    
    var a = 5;
    while(a<10){
      println(a)
      if(a==8){
        println(a+"跳出循环")
        break()
      }
      a+=1
    }
  }
}

scala 函数和方法的区别?

为了完成某一功能的程序指令(语句)的集合,即函数

类中的函数称之为 方法
函数是带有参数的表达式

方法由 `def` 定义,def 后面跟着 方法名、形参列表、返回类型和方法体

方法不能作为单独的表达式而存在(参数为空的方法除外),函数可以。

方法名是方法调用,函数名代表函数对象本身。

在需要函数的地方,如果传递一个方法,会自动进行ETA(把方法转换为函数)展开。

传名参数本质上是个方法

scala 函数的参数?

可变参数:参数的个数可变,但是参数的数据类型必须是指定的类型

def test(s: String*): Unit = {println(s)}
test("Hello","World","Hello","Scala")
// ArraySeq(Hello, World, Hello, Scala)

def test(s:Any*): Unit = {println(s)}
test("Hello","World","Hello",2,2.5)
// ArraySeq(Hello, World, Hello, 2, 2.5)

如果参数列表中存在多个参数,那么可变参数一般放置在最后。

def test2( name : String, s: String* )
{
   println(name + "," + s)
}
test2("汤姆","是个","男孩")
// 汤姆,ArraySeq(是个, 男孩)

参数可以设置默认值,在调用函数的时候,不给其传值,会使用默认值。

def test3(id: Int,name: String,gender: String ="男")=
{
	println(id+"\t"+name+"\t"+gender)
}
test3(2,"李四")
// 2	李四	男

带名传参

def test4(id: Int,name: String,age: Int)={println(id+"\t"+name+"\t"+age)}
test4(name="张三",id=4,age=18)
// 4	张三	18

scala 方法的几种写法?

    // 无参无返回值
    def test{
      println("无参无返回值")
    }
    test  // 无参无返回值
    // 无参有返回值
    def test1: Int={
      println("无参有返回值")
      25
    }
    println(test1)  // 无参有返回值 // 25
    // 有参无返回值
    def test2(name: String){
      println(name+"有参无返回值")
    }
    test2("王五")  // 王五有参无返回值
    // 有参有返回值
    def test3(name: String): String = {
      println(name+"有参有返回值")
      name
    }
    println(test3("张三"))  // 张三有参有返回值 // 张三
    // 多参无返回值
    def test4(id: Int,name: String,age: Int)
    {
      println(id+"\t"+name+"\t"+age)
    }
    test4(5,"李四",25)  // 5	李四	25

scala 函数的写法

// 无参无返回值
val test = println("无参无返回值")
// 无参有返回值
val test1 => (Int) = 25
// 有参无返回值
val test2(a: Int) = println(a)
// 有参有返回值
val test3(a: Int,b: Int) => (Int) = a+b
// 多参无返回值
val test4(a: Int,b: Int)(c: Int) = (a+b)*c

scala 闭包?

函数内部引入外部变量,即闭包。

闭包,就是将一个函数和其相关的引用环境(变量)组合的一个整体(实体)

scala 柯里化?

将一个接收多个参数的函数转化成一个接收一个参数的函数的过程,可以简单的理解为一种特殊的参数列表声明方式。

def test(id: Int,name: String,gender: String){}
def test(id: Int)(name: String)(gender: String){}

scala 函数至简原则?

能省则省

  1. return可以省略,Scala会使用函数体的最后一行代码作为返回值
  2. 返回值类型如果能够推断出来,可以省略。
  3. 函数体只有一行代码,可以省略花括号。
  4. 函数无参,可以省略小括号,定义函数时省略小括号,调用函数时也需省略小括号。
  5. 如果函数明确声明Unit,那么即使函数体中使用return关键字也不起作用。
  6. 如果不关心名称,只关心逻辑处理,def也可以省略。
  7. 如果函数明确使用return关键字,那么函数返回时就不能使用自行推断了,需要声明返回值类型。

scala lazy?

惰性函数:当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到首次访问,该函数才会执行。

def main(args: Array[String]): Unit = {
    println("使用lazy关键字>>>")
    lazy val res = sum(20,22)
    println("————————")
    println("res="+res)
    println("没有使用lazy关键字>>>")
    val res2 = sum(20,22)
    println("————————")
    println("res2="+res2)
}
def sum(n1: Int,n2: Int): Int = {
	println("<<<<【sum函数被执行了】>>>>")
	return n1 + n2
}
// console(控制台结果)
// 使用lazy关键字>>>
// ————————
// <<<<【sum函数被执行了】>>>>
// res=42
// 没有使用lazy关键字>>>
// <<<<【sum函数被执行了】>>>>
// ————————
// res2=42

Scala包的三大作用

Scala包的作用:

​ ① 区分相同名字的类

​ ② 当类很多时,可以很好地管理类

​ ③ 控制访问范围

scala中的三个默认导入包?

import java.lang._

import scala._

import scala.Predef._

scala 访问修饰符,及作用域?

scala中属性和方法的默认访问权限为 public,但scala中无public 关键字。

private 为私有权限,只在类的内部和伴生对象中可用。

protected 为受保护权限,Scala 中受保护权限比Java中更严格,同类、子类可以访问,同包无法访问。

private[包名]增加包访问权限,包名下的其他类也可以使用。

scala @BeanProperty 属性的特点?

使用 @BeanProperty 注解的属性可以自动生成规范的 读写器方法(settter/getter)

scala var和val 修饰的对象有什么区别?

val 修饰的对象不能改变对象的引用(即内存地址),可以改变对象属性的值。

var 修饰的对象可以修改对象的引用和修改对象的属性值

scala 的构造器?

Scala 类的构造器包括:主构造器和辅助构造器

主构造器即定义类的语法

class className(参数列表)
{
}

辅助构造器,函数的名称为 this 可以有多个,编译器通过参数的个数来区分。

辅助构造方法不能直接构建对象,必须直接或者间接调用主构造器方法。

def this(参数列表){
	// 调用主构造器
	this(参数列表)
}

构造器参数

未用任何修饰、var 修饰、val 修饰

未用任何修饰符修饰,这个参数就是一个局部变量。

var 修饰参数,作为类的成员属性使用,可以修改

val 修饰参数,作为类只读属性使用,不能修改。

scala 的继承?

基本语法:class 子类名 extends 父类名{类体}

子类继承父类的属性和方法

scala 是单继承

scala的抽象类?

//定义抽象类
abstract class Person{
    
}
//定义抽象属性,属性未初始化
val|var name: String
// 定义抽象方法,没有方法体
def hello(): String

scala的内部类访问的方法?

class OuterClass{
  val id:Int = 9527
  val name = "周星星"

  //内部类
  class InnerClass{
    val id:Int = 007
    val name = "凌凌漆"

    def getInfo = println( s"$id $name")
  }

  //外部类的方法 直接返回内部类对象
  def getInnerClass: InnerClass={
    val ic = new InnerClass
    ic
  }

}

/**
 *  访问内部类
 */
//第一种:通过new外部类对象,内部类创建内部类对象
val innerClass: OuterClass.InnerClass = new OuterClass.InnerClass
// 使用内部类对象名调用内部类的方法
innserClass.getInfo
//第二种:先创建外部类,用外部类对象名调用返回内部类对象的方法
val outerClass = new OuterClass
val innerClass02: outerClass.InnerClass = outerClass.getInnerClass
innerClass02.getInfo

scala object特点?

该对象是单例对象,若单例对象名与类名一致,则称该单例对象是这个类的伴生对象。

这个类的所有 " 静态 " 内容都可以放置在它的伴生对象中声明。

单例对象使用关键字 object 声明

单例对象对应的类称之为 伴生类,伴生对象的名称应该和伴生类名一致。

单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。

scala伴生类和伴生对象?

同一个scala文件中,class的名字和object的名字相同,即class是object 的伴生类,object是class的伴生对象。

scala 的apply?

object Test{
	def main(args: Array[String]): Unit = {
		//(1)通过伴生对象的apply方法,实现不使用new关键字创建对象。
        val p1 = Person()
        println("p1.name=" + p1.name)

        val p2 = Person("bobo")
        println("p2.name=" + p2.name)
	}
}
object Person {

    def apply(): Person = {
        println("apply空参被调用")
        new Person("xx")
    }

    def apply(name: String): Person = {
        println("apply有参被调用")
        new Person(name)
  	}
}

Scala中,采用trait(特质)代替接口的概念。也就是说,多个类具有相同的特征时,就可以将这个特质独立出来,采用关键字 trait 声明。

Scala 中的 trait 中既可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质。

Scala 引入 trait 特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。

一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了 extends 关键字,如果有多个特质或存在父类,那么需要采用with关键字连接。

使用

当一个类去继承特质时,第一个连接词是 extends,后面是with

如果一个类在继承特质和父类时,应当把父类写在 extends 后。

特质可以同时拥有抽象方法和具体方法。

一个类可以混入(mixin)多个特质。

所有的Java 接口都可以当做 Scala 特质使用

scala的类型检查和类型转换?

类型检查:对象名.isInstanceOf[类名] 或者 对象名.getClass classof 类名

类型转换:对象名.asInstanceOf[类名]

使用 type 为数据类型设置别名

type 别名 = 数据类型
var v:别名 = “abc”

scala 数组?

不可变数组

1)第一种方式定义数组(定长数组)

定义:val arr1 = new ArrayInt

(1)new是关键字

(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any

(3)(10),表示数组的大小,确定后就不可以变化

定义数组

val arr1 = Array(1, 2)

(1)在定义数组时,直接赋值

(2)使用apply方法创建数组对象

可变数组

1)定义变长数组

val arr01 = ArrayBuffer[Any](3, 2, 5)

(1)[Any]存放任意数据类型

(2)(3, 2, 5)初始化好的三个元素

(3)ArrayBuffer需要引入scala.collection.mutable.ArrayBuffer

ArrayBuffer是有序的集合

(2)增加元素使用的是append方法(),支持可变参数

不可变数组与可变数组的转换

1)说明

arr1.toBuffer //不可长数组转可变数组

arr2.toArray //可变数组转不可变数组

(1)arr2.toArray返回结果才是一个不可变数组+,arr2本身没有变化

(2)arr1.toBuffer返回结果才是一个可变数组,arr1本身没有变化

多维数组

1)多维数组定义

val arr =Array.ofDimDouble

说明:二维数组中有三个一维数组,每个一维数组中有四个元素

scala的list

不可变List

1)说明

(1)List默认为不可变集合

(2)创建一个List(数据有顺序,可重复)
(3)遍历List
(4)List增加数据

(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
(6)取指定数据
(7)空集合Nil

可变ListBuffer

1)说明

(1)创建一个可变集合ListBuffer

(2)向集合中添加数据

(3)打印集合数据

scala的map

Scala中的Map和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射,Scala中不可变的Map是有序的,可变的Map是无序的。

不可变Map

1)说明

(1)创建不可变集合Map

(2)循环打印

(3)访问数据

(4)如果key不存在,返回0

可变Map

1)说明

(1)创建可变集合

(2)打印集合

(3)向集合增加数据

(4)删除数据

(5)修改数据

scala的set

默认情况下,Scala使用的是不可变集合,如果你想使用可变集合,需要引用scala.collection.mutable.Set包

不可变Set

1)说明

(1)Set默认是不可变集合,数据无序

(2)数据不可重复

(3)遍历集合

不可变mutable.Set

1)说明

(1)创建可变集合mutable.Set

(2)打印集合

(3)集合添加元素

(4)向集合中添加元素,返回一个新的Set

(5)删除数据

scala的集合的head tail Nil?

构造列表是有两个基本类型Nil和:: //Nill也可以表示一个空列表

Scala列表有三个基本操作 /* head返回列表第一个元素tail返回一个列表,包含除了第一个元素之外的其他元素isEmpty在列表为空时返回true

scala的并行集合

Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

scala的队列

scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。

样例类的特点?

  • 案例类非常适合用于不可变的数据

  • 不能使用new来创建对象,这是因为案例类有一个默认的apply方法来负责对象的创建。

  • 使用==比较,可以直接比较堆和栈的上的值

  • 当你创建包含参数的案例类时,这些参数是公开(public)的val,不能为案例类的属性重新赋值

  • 拷贝:浅拷贝,只拷贝类的属性中(基本数据类型);深拷贝(不但拷贝基本数据类型还要拷贝引用数据类型)

  • 密封类
    (1)语法:
    case classPerson (name: String, age: Int)
    (2)说明

  1. 样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中自动提供了一些常用的方法,如apply、unapply、toString、equals、hashCode和copy。
  2. 样例类是为模式匹配而优化的类,因为其默认提供了unapply方法,因此,样例类可以直接使用模式匹配,而无需自己实现unapply方法。
  3. 构造器中的每一个参数都成为val,除非它被显式地声明为var(不建议这样做)

scala的模式匹配

Scala中的模式匹配类似于Java中的switch语法,但是更加强大。
模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _分支,类似于Java中default语句。

说明

(1)如果所有case都不匹配,那么会执行case _分支,类似于Java中default语句,若没有case _分支,那么会抛出MatchError。

(2)每个case中,不用break语句,自动中断case。

(3)match case语句可以匹配任何类型,而不只是字面量。

(4)=>后面的代码块,是作为一个整体执行,可以使用{}括起来,也可以不括。

scala的偏函数

偏函数也是函数的一种,通过偏函数我们可以方便的对输入参数做更精确的检查。例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。
偏函数的功能能是返回输入的List集合的第二个元组

scala的异常

1)我们将可疑代码封装在try块中。在try块之后使用了一个catch处理程序来捕获异常。如果发生任何异常,catch处理程序将处理它,程序将不会异常终止。
2)Scala的异常的工作机制和Java一样,但是Scala没有“checked(编译期)”异常,即Scala没有编译异常这个概念,异常都是在运行的时候捕获处理。

3)异常捕捉的机制与其他语言中一样,如果有异常发生,catch子句是按次序捕捉的。因此,在catch子句中,越具体的异常越要靠前,越普遍的异常越靠后,如果把越普遍的异常写在前,把具体的异常写在后,在Scala中也不会报错,但这样是非常不好的编程风格。

4)finally子句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作,这点和Java一样。

5)用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。throw表达式是有类型的,就是Nothing,因为Nothing是所有类型的子类型,所以throw表达式可以用在需要类型的地方

def test():Nothing = {
    throw new Exception("不对")
}

6)Scala提供了throws关键字来声明异常。可以使用方法定义声明异常。它向调用者函数提供了此方法可能引发此异常的信息。它有助于调用函数处理并将该代码包含在try-catch块中,以避免程序异常终止。在Scala中,可以使用throws注释来声明异常

你可能感兴趣的:(scala)