scala学习笔记

1.概述
1.1特点

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

的静态类型编程语言。

1) Scala 是一门多范式 (multi-paradigm) 的编程语言,Scala 支持面向对象和函数式编程

2) Scala源代码(.scala)会被编译成Java字节码(.class),然后运行于JVM之上,并可以调用现有的 Java 类库,实现两种语言的无缝对接。[案例演示]

3) scala 单作为一门语言来看, 非常的简洁高效 (三元运算, ++ , --)

4) Scala 在设计时,马丁·奥德斯基 是参考了 Java 的设计思想,可以说 Scala 是源于 java,同时 马丁·奥德斯基 也加入了自己的思想,将函数式编程语言的特点融合到 JAVA 中, 因此,对于学习过 Java 的同学,只要在学习 Scala 的过程中,搞清楚 Scala 和 java 相同点和不同点,就可以快速的掌握 Scala 这门语言

5) 快速有效掌握 Scala 的三点建议 [1. 学习 **scala** 的特有的语法 **2.** 区别 **scala** 和 **Java 3.** 如何规 范使用 **scala**]


1.2java、scala和jvm的关系图

2.变量

2.1定义

var | val 变量名 [: 变量类型] = 变量值
  1. 声明变量时,类型可以省略(编译器自动推导,即类型推导)
  2. 类型确定后,就不能修改,说明 Scala 是强数据类型语言.
  3. 在声明/定义一个变量时,可以使用 var 或者 val 来修饰, var 修饰的变量可改变,val 修饰的变量不可改
  4. val修饰的变量在编译后,等同于加上final
  5. var 修饰的对象引用可以改变,val 修饰的则不可改变,但对象的状态(值)却是可以改变的。(比 如: 自定义对象、数组、集合等等) [分析 val 好处]
  6. 变量声明时,需要初始值

2.2数据类型

  1. Scala 与 Java 有着相同的数据类型,在 Scala 中数据类型都是对象,也就是说 scala 没有 java 中的原生类型
  2. Scala 数据类型分为两大类 AnyVal(值类型) 和AnyRef(引用类型), 注意:不管是 AnyVal 还 是 AnyRef 都是对象。[案例演示 Int , Char]
  3. 相对于 java 的类型系统,scala 要复杂些!也正是这复杂多变的类型系统才让面向对象编程和函 数式编程完美的融合在了一起

说明

  • 在 scala 中有一个根类型 Any ,他是所有类的父类.
  • scala中一切皆为对象,分为两大类AnyVal(值类型),AnyRef(引用类型),他们都是Any子类.
  • Null 类型是 scala 的特别类型,它只有一个值 null, 他是 bottom class ,是 所有 AnyRef 类型的子类
  • Nothing类型也是bottomclass,他是所有类的子类,在开发中通常可以将Nothing类型的值返回给任意变量或者函数, 这里抛出异常使用很多.
  • 在 scala 中仍然遵守,低精度的值,向高精度的值自动转换(implicit conversion) 隐式转换.

2.3关于Null、Unit、Nothing

  1. Null类只有一个实例对象,null,类似于Java中的null引用。null可以赋值给任意引用类型 (AnyRef),但是不能赋值给值类型(AnyVal: 比如 Int, Float, Char, Boolean, Long, Double, Byte, Short)
  2. Unit类型用来标识过程,也就是没有明确返回值的函数。由此可见,Unit类似于Java里的void。 Unit 只有一个实例,(),这个实例也没有实质的意义
  3. Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返 回,而且由于 Nothing 是其他任意类型的子类,他还能跟要求返回值的方法兼容。

2.4值类型转换

自动类型转换细节说明

1) 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。 5.6 + 10 = 》double

2) 当我们把精度(容量)大 的数据类型赋值给精度(容量)小 的数据类型时,就会报错,反之就会进行自动类型转换

3)  (byte, short) 和 char 之间不会相互自动转换。

4)  byte,short,char 他们三者可以计算,在计算时首先转换为 int 类型。

5)  自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型

3.流程控制

3.1顺序控制

程序从上到下逐行执行,中间没有任何判断和跳转

3.2分支控制

if (条件表达式 1) {
        执行代码块 1 
} else if (条件表达式 2) { 
        执行代码块 2
} else { 
        执行代码块 n
}

3.3switch 分支结构

后面详细讲解

3.4for 循环控制

Scala 也为 for 循环这一常见的控制结构提供了非常多的特性,这些 for 循环的特性被称为 **for** 推导式(for comprehension)或 **for** 表达式(for expression)

3.4.1范围数据循环方式 1

object ForDemo01 {
def main(args: Array[String]): Unit = {
        //输出 10 句 "hello,尚硅谷!" 
        val start = 1
        val end = 10
        //说明
        //1. start 从哪个数开始循环 //2. to 是关键字
        //3. end 循环结束的值
        //4. start to end 表示前后闭合 
        for (i <- start to end) {
            println("你好,world" + i) 
        }

        //说明 for 这种推导时,也可以直接对集合进行遍历 var list = List("hello", 10, 30, "tom")
        for (item <- list) {
                println("item=" + item) }
        } 
}

3.4.2范围数据循环方式 2

for(i <- 1 until 3) {
print(i + " ") }

3.4.3循环守卫

循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环体内部,为 false

则跳过,类似于 continue

for(i <- 1 to 3 if i != 2) {
    print(i + " ") 
}

3.4.4引入变量

for(i <- 1 to 3; j = 4 - i) {
    print(j + " ") 
}

// 没有关键字,所以范围后一定要加;来隔断逻辑 上面的代码等价
for ( i <- 1 to 3) { 
    valj=4 –i
    print(j+"") 
}

3.4.5嵌套循环

for(i <- 1 to 3; j <- 1 to 3) {
    println(" i =" + i + " j = " + j) 
}

// 没有关键字,所以范围后一定要加;来隔断逻辑 上面的代码等价
for ( i <- 1 to 3) { 
    for ( j <- 1to 3){
        println(i + " " + j + " ")
    } 
}

3.4.6循环返回值

val res = for(i <- 1 to 10) yield i 
println(res)

// 将遍历过程中处理的结果返回到一个新 Vector 集合中,使用 yield 关键字

3.4.7使用花括号{}代替小括号()

for(i<-1to3;j= i*2){
    println(" i= " + i + " j= " + j) 
}
// 可以写成
for{
i <- 1 to 3
j = i * 2} {
    println(" i= " + i + " j= " + j) 
}
  • {}和()对于 for 表达式来说都可以
  • for 推导式有一个不成文的约定:当 for 推导式仅包含单一表达式时使用圆括号,当其包含多个表达式时使用大括号
  • 当使用{} 来换行写表达式时,分号就不用写了

说明:

1) scala 的 for 循环形式和 java 是较大差异,这点请同学们注意,但是基本的原理还是一样的

2) scala 的 for 循环的步长如何控制! [for(i <- Range(1,3,2)]

3.5while循环控制

循环变量初始化 

while (循环条件) {

​        循环体(语句) 循环变量迭代

}

  1. 循环条件是返回一个布尔值的表达式
  2. while循环是先判断再执行语句
  3. 与 If 语句不同,While 语句本身没有值,即整个 While 语句的结果是 Unit 类型的()
  4. 因为 while 中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量 ,而变量需要声明在 while 循环的外部,那么就等同于循环的内部对外部的变量造成了影响,所以不推荐使 用,而是推荐使用 for 循环。

3.6do..while 循环控制

do {

​        循环体(语句) 循环变量迭代

} while(循环条件)

  1. 循环条件是返回一个布尔值的表达式
  2. do..while循环是先执行,再判断
  3. 和 while 一样,因为 do...while 中没有返回值

3.7多重循环控制

  1. 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do...while 均可以作为 外层循环和内层循环。【建议一般使用两层,最多不要超过 3 层】
  2. 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false 时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
  3. 设外层循环次数为 m 次,内层为 n 次, 则内层循环体实际上需要执行 m*n=mn 次。

3.8while 循环的中断

Scala 内置控制结构特地去掉了 break 和 continue,是为了更好的适应函数化编程,推荐使用函数式的风格解决 break 和 contine 的功能,而不是一个关键字。

//breakable()函数
//说明
//1. breakable 是一个高阶函数:可以接收函数的函数就是高阶函数(后面详解
breakable {
    while (n <= 20) { 
        n += 1
        println("n=" + n) if (n == 18) {
        //中断 while
        //说明
        //1. 在 scala 中使用函数式的 break 函数中断循环 
        //2. def break(): Nothing = { throw breakException } 
        break()
    } 
}

4函数式编程-基础篇

4.1几个概念

在学习 Scala 中将方法、函数、函数式编程和面向对象编程明确一下:

  1. 在 scala 中,方法和函数几乎可以等同(比如他们的定义、使用、运行机制都一样的),只是函数 的使用方式更加的灵活多样。
  2. 函数式编程是从编程方式(范式)的角度来谈的,可以这样理解:函数式编程把函数当做一等公 民,充分利用函数、 支持的函数的多种使用方式。
  3.  比如:在 Scala 当中,函数是一等公民,像变量一样,既可以作为函数的参数使用,也可以将函数赋值给一个 变量. ,函数的创建不用依赖于类或者对象,而在 Java 当中,函数的创建则要依赖于类、抽象类或者 接口.
  4. 面向对象编程是以对象为基础的编程方式
  5. 在 scala 中函数式编程和面向对象编程融合在一起了

在学习 Scala 中将方法、函数、函数式编程和面向对象编程关系分析图:

4.2函数式编程的小结

  1. "函数式编程"是一种"编程范式"(programming paradigm)
  2. 它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用
  3. 函数式编程中,将函数也当做数据类型,因此可以接受函数当作输入(参数)和输出(返回值)
  4. 函数式编程中,最重要的就是函数

4.3函数的定义

def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] { 
​        语句...
​        return 返回值 
}

  1. 函数声明关键字为 def (definition)
  2. [参数名: 参数类型], ...:表示函数的输入(就是参数列表), 可以没有。 如果有,多个参数使用 逗号间隔
  3. 函数中的语句:表示为了实现某一功能代码块
  4. 函数可以有返回值,也可以没有
    返回值形式 1:   全写,正常行驶
    返回值形式 2:  () =  {xxx}  表示返回类型不确定,使用推导类型
    返回值形式 3:  (xxx){xxx}    表示没有返回值,return 不生效
  5. 如果没有 return ,默认以执行到最后一行的结果作为返回值

4.4 函数调用机制

4.4.1调用过程

4.4.2函数递归调用的重要的规则和小结

  函数递归需要遵守的重要原则(总结):

  1. 程序执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
  2. 函数的局部变量是独立的,不会相互影响
  3. 递归必须向退出递归的条件逼近,否则就是无限递归,死龟了:)
  4. 当一个函数执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁。

4.4.3 函数注意事项和细节讨论

  • 函数的形参列表可以是多个, 如果函数没有形参,调用时 可以不带()
  • 形参列表和返回值列表的数据类型可以是值类型和引用类型
  • Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下, return 关键字可以省略
  • 因为 Scala 可以自行推断,所以在省略 return 关键字的场合,返回值类型也可以省略
  • 如果函数明确使用 return 关键字,那么函数返回就不能使用自行推断了,这时要明确写成 : 返回类型 = ,当然如果你什么都不写,即使有 return 返回值为()
  • 如果函数明确声明无返回值(声明 Unit),那么函数体中即使使用 return 关键字也不会有返回 值
  • 如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为 Any
  • Scala语法中任何的语法结构都可以嵌套其他语法结构(灵活),即:函数中可以再声明/定义函数, 类中可以再声明类 ,方法中可以再声明/定义方法
  • Scala函数的形参,在声明参数时,直接赋初始值(默认值),这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值。
  • 如果函数存在多个参数,每一个参数都可以设定默认值,那么这个时候,传递的参数到底是覆 盖默认值,还是赋值给没有默认值的参数,就不确定了(默认按照声明顺序[从左到右])。在这种情况下, 可以采用带名参数
  • 递归函数未执行之前是无法推断出来结果类型,在使用时必须有明确的返回值类型
  • Scala函数支持可变参数

1. args 是集合, 通过 for 循环 可以访问到各个值。
2. 案例演示: 编写一个函数 sum ,可以求出 1 到多个 int 的和
3. 可变参数需要写在形参列表的最后。

4.4.4过程

将函数的返回类型为Unit的函数称之为过程(procedure),如果明确函数没有返回值,那么等号可以省略

1) 注意区分: 如果函数声明时没有返回值类型,但是有 = 号,可以进行类型推断最后一行代码。 这时这个函数实际是有返回值的,该函数并不是过程。(这点在讲解函数细节的时候讲过的.)

2) 开发工具的自动代码补全功能,虽然会自动加上 Unit,但是考虑到 Scala 语言的简单,灵活, 最好不加.

4.5惰性函数

当函数返回值被声明为 lazy 时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。

这种函数我们称之为惰性函数,在 Java 的某些框架代码中称之为懒加载(延迟加载)。

object LazyDemo01 {
        def main(args: Array[String]): Unit = { 
                lazy val res = sum(10, 20) 
                println("-----------------")
                println("res=" + res) //在要使用 res 前,才执行 
        }
        //sum 函数,返回和
        
        def sum(n1: Int, n2: Int): Int = {
                println("sum() 执行了..") //输出一句话
                return n1 + n2 
        }
}

1) lazy 不能修饰 var 类型的变量

2) 不但是 在调用函数时,加了 lazy ,会导致函数的执行被推迟,我们在声明一个变量时,如果给 声明了 **lazy ,**那么变量值得分配也会推迟。 比如 lazy val i = 10

4.6 异常

Scala提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发 生的异常。可以根据需要在程序中有任意数量的 try...catch 块。

语法处理上和 Java 类似,但是又不尽相同

4.6.1Java 异常处理的注意点.

  1. java语言按照try—catch-catch...—finally的方式来处理异常
  2. 不管有没有异常捕获,都会执行 **finally**, 因此通常可以在 finally 代码块中释放资源
  3. 可以有多个 catch,分别捕获对应的异常,这时需要把范围小的异常类写在前面,把范围大的异

常类写在后面,否则编译错误。会提示 "Exception 'java.lang.xxxxxx' has already been caught"

4.6.2Scala 异常处理小结

  1. 我们将可疑代码封装在 **try** 块中。 在 try 块之后使用了一个 catch 处理程序来捕获异常。如果发 生任何异常,catch 处理程序将处理它,程序将不会异常终止。
  2. Scala的异常的工作机制和Java一样,但是**Scala**没有“**checked(**编译期**)**”异常,即Scala没有 编译异常这个概念,异常都是在运行的时候捕获处理。
  3. 用 throw关键字,抛出一个异常对象。所有异常都是 Throwable 的子类型。throw 表达式是有类 型的,就是 Nothing,因为 Nothing 是所有类型的子类型,所以 throw 表达式可以用在需要类型的地方
  4. 在 Scala 里,借用了模式匹配的思想来做异常的匹配,因此,在 catch 的代码里,是一系列 case 子句来匹配异常。【前面案例可以看出这个特点**,** 模式匹配我们后面详解】,当匹配上后 => 有多条 语句可以换行写,类似 java 的 switch case x: 代码块..
  5. 异常捕捉的机制与其他语言中一样,如果有异常发生,catch 子句是按次序捕捉的。因此,在 catch子句中,越具体的异常越要靠前,越普遍的异常越靠后,如果把越普遍的异常写在前,把具体异常写在后,在 **scala** 中也不会报错,但这样是非常不好的编程风格。
  6. finally子句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作,这点和 Java 一样。
  7. Scala提供了throws关键字来声明异常。可以使用方法定义声明异常。它向调用者函数提供了此方法可能引发此异常的信息。 它有助于调用函数处理并将该代码包含在 try-catch 块中,以避免程序 异常终止。在 scala 中,可以使用 throws 注释来声明异常

5.面向对象编程-基础部分

5.1类和对象

  1. Java是面向对象的编程语言,由于历史原因,Java中还存在着非面向对象的内容:基本类型, null,静态方法等。
  2. Scala语言来自于Java,所以天生就是面向对象的语言,而且Scala是纯粹的面向对象的语言, 即在 Scala 中,一切皆为对象。
  3. 在面向对象的学习过程中可以对比着 Java 语言学习

5.1.1类和对象的区别和联系

  1. 类是抽象的,概念的,代表一类事物,比如人类,猫类.. 
  2. 对象是具体的,实际的,代表一个具体事物
  3. 类是对象的模板,对象是类的一个个体,对应一个实例 
  4. Scala 中类和对象的区别和联系 和 Java 是一样的。

5.1.2 如何定义类

基本语法
[修饰符] class 类名 { 
​        类体
}

定义类的注意事项

  1. scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public),[修饰符在后面再详解].
  2. 一个 Scala 源文件可以包含多个类.,而且默认都是 public

5.1.3属性

属性是类的一个组成部分,一般是值数据类型,也可是引用类型。比如我们前面定义猫类 的 age 就是属性

5.1.4属性/成员变量

注意事项和细节说明

1) 属性的定义语法同变量,示例:[访问修饰符] var 属性名称 [:类型] = 属性值

2) 属性的定义类型可以为任意类型,包含值类型或引用类型[案例演示]

3) Scala中声明一个属性,必须显示的初始化,然后根据初始化数据的类型自动推断,属性类型可以省略(这点和 Java 不同)。

4) 如果赋值为 null,则一定要加类型,因为不加类型, 那么该属性的类型就是 Null 类型.

5) 如果在定义属性时,暂时不赋值,也可以使用符号_(下划线),让系统分配默认值.

5.1.5属性的高级部分

说明:属性的高级部分和构造器(构造方法/函数) 相关,我们把属性高级部分放到构造器那里讲解。

5.1.6如何创建对象

val | var 对象名 [:类型] = new 类型()

1) 如果我们不希望改变对象的引用(即:内存地址), 应该声明为 val 性质的,否则声明为 var, scala设计者推荐使用 val ,因为一般来说,在程序中,我们只是改变对象属性的值,而不是改变对象的引用

2) scala在声明对象变量时,可以根据创建对象的类型自动推断,所以类型声明可以省略,但当类型和后面 new对象类型有继承关系即多态时,就必须写了

5.2方法

Scala 中的方法其实就是函数,声明规则请参考函数式编程中的函数声明。

def 方法名(参数列表) [:返回值类型] = { 
        方法体
}

5.3构造器

[修饰符] 方法名(参数列表){ 构造方法体}
class 类名(形参列表) { // 类体
    def this(形参列表) { }
    def this(形参列表) { }
    // 主构造器
    // 辅助构造器 //辅助构造器可以有多个...
}
  1. Scala构造器作用是完成对新对象的初始化,构造器没有返回值。
  2. 主构造器的声明直接放置于类名之后 [反编译]
  3. 主构造器会执行类定义中的所有语句,这里可以体会到 Scala 的函数式编程和面向对象编程融 合在一起,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别
  4. 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略
  5. 辅助构造器名称为 this(这个和 Java 是不一样的),多个辅助构造器通过不同参数列表进行区 分, 在底层就是 f 构造器重载
  6. 如果想让主构造器变成私有的,可以在()之前加上 private,这样用户只能通过辅助构造器来构 造对象了
  7. 辅助构造器的声明不能和主构造器的声明一致,会发生错误(即构造器名重复)

5.4构造器参数

5.4.1说明

  1. Scala类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量。
  2. 如果参数使用val关键字声明,那么Scala会将参数作为类的私有的只读属性使用【案例+反编 译】
  3. 如果参数使用var关键字声明,那么那么 Scala 会将参数作为类的成员属性使用,并会提供属性 对应的 xxx()[类似 getter]/xxx_$eq()[类似 setter]方法,即这时的成员属性是私有的,但是可读写。

5.4.2Bean 属性

JavaBeans 规范定义了 Java 的属性是像 getXxx()和 setXxx()的方法。许多 Java 工具(框架) 都依赖这个命名习惯。为了 Java 的互操作性。将 Scala 字段加@BeanProperty 时,这样会自动生成规范 的 setXxx/getXxx 方法。这时可以使用 对象.setXxx() 和 对象.getXxx() 来调用属性。

注意:给某个属性加入@BeanPropetry注解后,会生成getXXX和setXXX方法,并且对原来底层自动生成类似 xxx(),xxx_$eq()方法,没有冲突,二者可以共存

6.集合

6.1集合特点

6.1.1scala集合基本介绍

  • scala同时支持不可变和可变集合,不可变集合可以安全的并发访问,两个主要的包:

不可变集合:scala.collection.immutable
可变集合:scala.collection.mutable

  • scala默认采用不可变集合,对于几乎所有的集合类,scala都同时提供了可变和不可变的版本
  • scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质,

6.1.2可变集合和不可变集合

  1. 不可变集合:scala不可变集合,就是这个集合本身不能动态变化。类似于java的数组,是不可以动态增长的
  2. 可变集合:就是这个集合本身可以动态变化(比如ArrayList,是可以动态增长的)

6.2不可变集合继承层次一览图

  1. set、map是java中也有的集合
  2. seq是java没有的,我们发现List归属到Seq了,因此这里的List和java不是一个概念
  3. 我们前面的for循环有一个1 to 3,就是IndexSeq下的Vector
  4. String也是属于IndexSeq
  5. 我们发现经典的数据结构比Queue和Stack被归属到LinearSeq
  6. scala中的map体系也有一个SortedMap,说明scala的Map可以支持排序
  7. IndexSeq和LinearSeq的区别是通过索引来查找和定位,因此速度快,比如String就是一个索引集合,通过索引即可定位LineaSeq是线性的,即有头尾的概念

6.3可变集合继承层次一览图

  1. 在可变集合中比不可变集合更加丰富
  2. 在 Seq 集合中, 增加了 Buffer 集合,将来开发中,我们常用的有 ArrayBuffer 和 ListBuffer
  3. 如果涉及到线程安全可以选择使用 syn.. 开头的集合
  4. 其它的说明参考不可变集合

6.4数组

6.4.1定长数组

// 方法一
//这里的数组等同于 Java 中的数组,中括号的类型就是数组的类型 
val arr1 = new Array[Int](10)
//赋值,集合元素采用小括号访问
arr1(1) = 7


// 方法二
//在定义数组时,直接赋值
//使用 apply 方法创建数组对象 
val arr1 = Array(1, 2)

代码参考

6.4.2变长数组

val arr2 = ArrayBuffer[Int]() 
//追加值/元素 
arr2.append(7)
//重新赋值
arr2(0) = 7

1) ArrayBuffer是变长数组,类似java的ArrayList
2) val arr2 = ArrayBuffer[Int]() 也是使用的 apply 方法构建对象
3) def append(elems: A*) { appendAll(elems) } 接收的是可变参数.
4) 每 append 一次,arr 在底层会重新分配空间,进行扩容,arr2 的内存地址会发生变化,也就成 为新的 ArrayBuffer

代码参考

6.4.3数组-Scala 数组与 Java 的 List 的互转

代码参考

6.5元组tuple

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。
说的简单点,就是将多个无关的数据封装为一个整体,称为元组, 最多的特点灵活,对数据没有过 多的约束
注意:元组中最大只能有 22 个元素

代码参考

6.6List

Scala 中的 List 和 Java List 不一样,在 Java 中 List 是一个接口,真正存放数据是 ArrayList,而 Scala 的 List 可以直接存放数据,就是一个 object

默认情况下 Scala 的 List 是不可变的,List 属于序列 Seq
val List = scala.collection.immutable.List object List extends SeqFactory[List]

6.6.1创建

  • List默认为不可变的集合
  • List 在 scala 包对象声明的,因此不需要引入其它包也可以使用 val List = scala.collection.immutable.List
  • List 中可以放任何数据类型,比如 arr1 的类型为 List[Any]
  • 如果希望得到一个空列表,可以使用 Nil 对象, 在 scala 包对象声明的,因此不需要引入其它包也可以使用val Nil = scala.collection.immutable.Nil

6.6.2元素的追加

向列表中增加元素, 会返回新的列表/集合对象。注意:Scala 中 List 元素的追加形式非常独特,和 Java 不一样。

需注意以下几点

  1. 符号::表示向集合中 新建集合添加元素。
  2. 运算时,集合对象一定要放置在最右边,
  3. 运算规则,从右向左。
  4. ::: 运算符是将集合中的每一个元素加入到集合中去

代码参考

6.7ListBuffer

ListBuffer 是可变的 list 集合,可以添加,删除元素,ListBuffer 属于序列 //追一下继承关系即可
Seq var listBuffer = ListBuffer(1,2)

代码参考

6.8队列

1) 队列是一个有序列表,在底层可以用数组或是链表来实现。
2) 其输入和输出要遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取 
3) 在 Scala 中,由设计者直接给我们提供队列类型 Queue 使用。
4) 在 scala 中, 有 scala.collection.mutable.Queue 和 scala.collection.immutable.Queue , 一般来说,我们在开发中通常使用可变集合中的队列

参考代码

6.9Map

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值