Spark--Scala基础知识总结(第二章)

目录

安装与运行Scala

了解scala

Scala特性

面向对象 函数式编程 静态类型 可扩展

安装scala

1. 在网页上运行Scala

​编辑2.Scala环境设置

​编辑3.Scala安装

1)在Linux和macOS系统上安装Scala

(2)在Windows系统上安装Scala

(3)在Windows系统上安装Scala

​编辑

运行Scala

​编辑​编辑

定义函数识别函数类型

了解数据类型

Scala常用数据类型

统计广州号码段数量

使用if判断

使用for循环

任务实现

根据归属地对手机号码段进行分组

定义与使用列表

列表操作常用方法

定义与使用集合

集合操作常用方法

定义与使用映射 

定义与使用元组 

用函数组合器 

 任务实现

编写手机号码归属地信息

 定义Scala类

使用Scala单例模式 

使用Scala模式匹配 

读写文件 

任务实现 

循环控制

 for循环

while循环

面向对象编程

 面向对象编程基础

 包

 导入

 属性

 访问权限

方法

构造方法

 面向对象进阶

继承

抽象

特质

集合

 数组

不可变数组

 可变数组

Seq集合

不可变List

 可变List

 Set集合

 不可变Set 可变Set

Map集合

 不可变Map

可变Map

元组

常用方法


 

安装与运行Scala

了解scala

ScalaScalable Language的缩写,是一种多范式的编程语言,由洛桑联邦理工学院的马丁·奥德斯在2001年基于Funnel的工作开始设计,设计初衷是想集成面向对象编程和函数式编程的各种特性。

Scala 是一种纯粹的面向对象的语言,每个值都是对象。Scala也是一种函数式语言,因此函数可以当成值使用。

由于Scala整合了面向对象编程和函数式编程的特性,因此Scala相对于JavaC#C++等其他语言更加简洁。

Scala源代码会被编译成Java字节码,因此Scala可以运行于Java虚拟机(Java Virtual MachineJVM)之上,并可以调用现有的Java类库。

Scala特性

面向对象 函数式编程 静态类型 可扩展

安装scala

1. 在网页上运行Scala

通过浏览器查找Scastie并进入,即可进入Scala在线运行环境。

进入Scastie界面后,在上窗格中输入“println("hello world")”

单击“Run”按钮,输出信息将显示在下窗格中,如下图。

2Scala环境设置

Scala运行环境众多,可以运行在WindowsLinuxmacOS等系统上。Scala是运行在JVM上的语言,因此必须确保系统环境中安装了JDK,即Java开发工具包,而且必须确保JDK版本与本书安装的SparkJDK编译版本一致,本书中使用的JDKJDK 8Java 1.8)。

查看Java版本

3Scala安装

1)在LinuxmacOS系统上安装Scala

Scala官网下载Scala安装包,安装包名称为“scala-2.12.15.tgz

将其上传至/opt目录

解压安装包至/usr/local目录下

配置Scala环境变量

2)在Windows系统上安装Scala

Scala官网下载Scala安装包,安装包名称为“scala.msi

双击scala.msi安装包,开始安装软件。

进入欢迎界面,单击右下角的“Next”按钮后出现许可协议选择提示框,选择接受许可协议中的条款并单击右下角的“Next”按钮。

(3)在Windows系统上安装Scala

选择安装路径,本文Scala的安装路径选择在非系统盘的“D:\Program Files (x86)\spark\scala\” ,单击“OK”按钮进入安装界面。

在安装界面中单击右下角的“Install”按钮进行安装,安装完成时单击“Finish”按钮完成安装。

右键单击“此电脑”图标,选择“属性”选项,在弹出的窗口中选择“高级系统设置”选项。在弹出的对话框中选择“高级”选项卡,并单击“环境变量”按钮,在环境变量对话框中,选择“Path”变量并单击“编辑”按钮,在Path变量中添加Scala安装目录的bin文件夹所在路径,如“D:\Program Files (x86)\spark\scala\bin”

运行Scala

Scala解释器也称为REPLRead-Evaluate-Print-Loop,读取-执行-输出-循环)。

在命令行中输入“scala,即可进入REPL,如下图。

REPL是一个交互式界面,用户输入命令时,可立即产生交互反馈。

输入“:quit”命令即可退出REPL,如下图。

图是一个Scala类,该类实现了两个数相加的方法。如果要使用该方法,那么需要通过import加载该方法,如下图,其中,add是类名,addInt是方法名。

定义函数识别函数类型

了解数据类型

Scala常用数据类型

数据类型

描述

Int

32位有符号补码整数。数值区间为−3276832767

Float

32IEEE754IEEE浮点数算术标准)单精度浮点数

Double

64IEEE754IEEE浮点数算术标准)双精度浮点数

String

字符序列,即字符串

Boolean

布尔值,truefalse

Unit

表示无值,作用与Java中的void一样,是不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()

Scala会区分不同类型的值,并且会基于使用值的方式确定最终结果的数据类型,这称为类型推断。

Scala使用类型推断可以确定混合使用数据类型时最终结果的数据类型。

如在加法中混用IntDouble类型时,Scala将确定最终结果为Double类型,如下图。

统计广州号码段数量

使用if判断

在实际业务中,经常需要对数据进行过滤处理,使用if判断即可满足这个需求。

Scala中的if判断根据复杂程度可分为if语句、if…else语句、if…else if…else语句、if…else嵌套语句,语法格式如下。

# if语句

if(布尔表达式) { 若布尔表达式为true,则执行该语句块}

# if…else语句

if(布尔表达式) { 若布尔表达式为true,则执行该语句块}

else { 若布尔表达式为false,则执行该语句块}

# if…else if…else语句

if(布尔表达式1) {

   若布尔表达式1true,则执行该语句块

} else if(布尔表达式2) {

      若布尔表达式2true,则执行该语句块

} else if(布尔表达式3) {

      若布尔表达式3true,则执行该语句块

}else {

      若以上布尔表达式都为false,则执行该语句块

# if…else嵌套语句

if (布尔表达式1) {

   if(布尔表达式2) {      若布尔表达式2true,则执行该语句块

   } else if(布尔表达式3) {      若布尔表达式3true,则执行该语句块

   } else {      若布尔表达式2false且布尔表达式3false,则执行该语句块

   }

} else {    若以上条件都为false,则执行该语句块

}

使用for循环

循环是指在某种条件下将一段代码按顺序重复执行。在Scala中有3种循环结构,分别为while循环、do…while循环和for循环。

for循环是相对较为常用的一种循环,for循环语法格式如下。

for(变量<- 集合) {循环语句}

多重循环是常见的for循环,多重循环也称为for循环嵌套,是指在两个或多个区间内循环反复,多个循环区间用分号隔开。

Scala可以在for循环中使用if判断过滤一些元素,多个过滤条件用分号隔开。

for循环使用yield可以将返回值作为一个变量存储,语法格式如下。

var retVar = for(var x <- List; if condition1; if condition2…) yield x

retVar是变量名,for关键字后的括号用于指明变量和条件,而yield会将每一次循环得到的返回值保存在一个集合中,循环结束后将返回该集合,并赋值给变量retVar

使用yield110的偶数进行记录,并保存至变量even中,如下图。

任务实现

定义函数count(area:String)统计广州号码段数量,首先使用一个数组存储数据,初始化sum0,再遍历该数组,判断数组中的元素是否包含参数area,若是则sum1

调用并执行count(“广州”)函数,结果如下图。

根据归属地对手机号码段进行分组

定义与使用列表

列表操作常用方法

方法

描述

def head: A

获取列表的第一个元素

def init:List[A]

返回所有元素,除了最后一个元素

def last:A

获取列表的最后一个元素

def tail:List[A]

返回所有元素,除了第一个元素

def :::(prefix: List[A]): List[A]

在列表开头添加指定列表的元素

def take(n: Int): List[A]

获取列表前n个元素

def contains(elem: Any): Boolean

判断列表是否包含指定元素

1.Scala 中常用的查看列表元素的方法有 head init last tail take()
head :查看列表的第一个元素。
tail :查看第一个元素之后的其余元素。
last :查看列表的最后一个元素。
Init :查看除最后一个元素外的所有元素。
take() :查看列表前 n 个元素。

2.如果需要合并两个列表,那么可以使用:::()。但需要注意,“列表1:::列表2”与“列表1.:::(列表2)”的结果是不一样的,对于前者,列表2的元素添加在列表1的后面;对于后者,列表2的元素添加在列表1的前面。合并两个列表还可以使用concat()方法。用户可以使用contains()方法判断列表中是否包含某个元素,若列表中存在指定的元素则返回true,否则返回false

定义与使用集合

Scala Set( 集合 ) 是没有重复的对象集合,所有的元素都是唯一的
集合操作常用方法

方法

描述

def head: A

获取集合的第一个元素

def init:Set[A]

返回所有元素,除了最后一个

def last:A

获取集合的最后一个元素

def tail:Set[A]

返回所有元素,除了第一个

def ++(elems: A): Set[A]

合并两个集合

def take(n: Int): List[A]

获取列表前n个元素

def contains(elem: Any): Boolean

判断集合中是否包含指定元素

Scala合并两个列表时使用的是:::()concat()方法,而合并两个集合使用的是++()方法。

定义与使用映射 

Ø 映射( Map 是一种可迭代的键值对结构
Ø 所有的值都可以通过键来获取 ,并且映射中的键都是唯一的
Ø 集合操作常用方法同样也适合映射。
Ø 另外映射还可以通过 keys 方法获取所有的键,通过 values 方法获取所有值,也可以通过 isEmpty 方法判断映射的数据是否为空

定义与使用元组 

Ø 元组( Tuple )是一种类似于列表的结构,但与列表不同的是,元组可以包含不同类型的元素。
Ø 元组的值是通过将单个的值包含在圆括号中构成的
Ø 目前, Scala 支持的元组最大长度为 22 ,即 Scala 元组最多只能包含 22 个元素。
Ø 访问元组元素可以通过“元组名称 ._ 元素索引”进行,索引从 1 开始。

用函数组合器 

Ø map() 方法 可通过一个函数重新计算列表中的所有元素,并且返回一个包含相同数目元素的新列表。
Ø foreach() 方法 map() 方法类似,但是 foreach() 方法没有返回值,只用于对参数的结果进行输出。

        Ø ilter()方法可以移除传入函数的返回值为false的元素。 

       

Ø flatten() 方法 可以将嵌套的结构展开,即 flatten() 方法可以将一个二维的列表展开成一个一维的列表。

          ØflatMap()方法结合了map()方法和flatten()方法的功能,接收一个可以处理嵌套列表的函               数,再对返回结果进行连接。 

ØgroupBy()方法可对集合中的元素进行分组操作,返回的结果是一个映射。 

 任务实现

 Ø实现根据归属地对手机号码段进行分组,需要先将数据存储至列表中,使用groupBy()方法对列表中的元素进行分组。

Ø从原始数据中抽取4条数据,并存放至列表phone中,使用groupBy()方法根据归属地对列表中的元素进行分组。

编写手机号码归属地信息

 定义Scala类

Ø Scala 是一种纯粹的面向对象语言,面向对象语言有两个重要的概念:类和对象
Ø 其中,类是对象的抽象,也可以把类理解为模板,对象才是真正的实体
Ø 一般定义类的格式如下。

class ClassName(参数列表) extendst {}

Ø 一个 Scala 源文件中可以有多个类,并且 Scala 类可以有参数。
Ø 一般, Scala 类名的第一个字母需要大写,如果需要使用几个单词构成一个类的名称,那么每个单词的第一个字母都要大写。
Ø Java 等其他语言不同的是, Scala 中的类不定义为 public
Ø Scala 类继承一个类时需要使用关键字 extends
Ø Scala 只允许继承一个父类,并且继承父类的所有属性和方法。
Ø 子类继承父类中已经实现的方法时,需要使用 override 关键字,子类继承父类中未实现的方法时,可以不用 override 关键字。

使用Scala单例模式 

Ø Scala 中没有 static 关键字,因此 Scala 的类中不存在静态成员。但是 Scala 可以使用 object 关键字实现单例模式。
Ø Scala 中使用单例模式时需要使用 object 定义一个单例对象( object 对象),单例对象在整个程序中只有一个实例。单例对象与类的区别在于单例对象不能带参数。
Ø 定义单例对象的语法如下。

object ObjectName {}

Ø 包含 main 方法的 object 对象可以作为程序的入口点。
Ø 当单例对象与某个类共享同一个名称时,单例对象被称作这个类的伴生对象,类被称为这个单例对象的伴生类。类和它的伴生对象可以互相访问对方的私有成员。
Ø 需要注意的是,必须在同一个源文件里定义类和它的伴生对象。

使用Scala模式匹配 

Ø Scala 提供了强大的模式匹配机制。一个模式匹配包含了一系列备选项,每个都开始于关键字 case 。每个备选项都包含了一个模式及一到多个表达式。模式和表达式之间用 => 隔开
Ø Scala 中,使用 case 关键字定义的类称为样例类。样例类是一种特殊的类,经过优化可应用于模式匹配。
Ø Scala 编译器为样例类添加了一些语法上的便捷设定,具体如下。
在伴生对象中提供了 apply() 方法,因此不使用 new 关键字也可以构造对象。
样例类参数列表中的所有参数已隐式获得 val 关键字。
编译器为样例类添加了 toString () hashCode () equals() 等方法。

读写文件 

Ø 在实际的实践中,常常需要涉及文件的读写操作
Ø Scala 不提供任何特殊文件写入能力,所以进行文件的写操作使用的是 Java I / O 类中的 PrintWriter 来实现
Ø 有时候需要接收用户在屏幕上输入的指令来处理程序,这时可以使用 StdIn.readLine 接收用户输入的指令。用户可以在 REPL 中直接输入“ StdIn.readLine ”命令并按“ Enter ”键,并在屏幕上输入指令;也可以将 StdIn.readLine 赋值给一个变量,用户在屏幕上输入的内容即可赋值给该变量。

  Ø用户可以使用ScalaSource类读取文件内容。

任务实现 

Ø 读取完整数据,编写程序完成手机号码归属地信息查询。将 2020phonelocation.txt 文件上传至 Linux 虚拟机的 /opt 目录下。
首先使用 object 定义一个单例对象 Phone ,在该对象中定义一个 checkPhone 方法,读取完整的数据,并将数据存储在一个列表中,使用 Console.readLine 接收用户输入的指令,用户在屏幕上输入要查询的手机号码段,程序接收到屏幕上的指令之后遍历存储数据的列表,若列表中某个元素包含该指令则输出该元素。
使用 paste 模式粘贴代码。调用单例对象 Phone 中的 checkPhone 方法,在屏幕上输入一个手机号码段,按“ Enter ”键输出该手机号码段的信息。

循环控制

 for循环

  • 基本语法:

for ( 循环变量 <- 数据集 ) {

​ 循环体

}

这里的数据集可以是任意类型的数据集合

object ScalaLoop {
    def main(args: Array[String]): Unit = {
        for ( i <- Range(1,5) ) { // 范围集合 [1,5)
            println("i = " + i )
        }
        for ( i <- 1 to 5 ) { // [1,5]
            println("i = " + i )
        }
        for ( i <- 1 until 5 ) { // 不包含5
            println("i = " + i )
        }
    }
}
  • 循环守卫

循环时可以增加条件来决定是否继续循环体的执行,这里的判断条件我们称之为循环守卫

for ( i <- Range(1,5) if i != 3  ) {
            println("i = " + i )
        }
  • 循环步长

scala的集合也可以设定循环的增长幅度,也就是所谓的步长step

for ( i <- Range(1,5,2) ) {
            println("i = " + i )
        }
for ( i <- 1 to 5 by 2 ) {
            println("i = " + i )
        }

while循环

语法
while( 循环条件表达式 ) {

​ 循环体

}

循环中断
​ scala是完全面向对象的语言,所以无法使用break,continue关键字这样的方式来中断,或继续循环逻辑,而是采用了函数式编程的方式代替了循环语法中的break和continue
Breaks.break是依靠抛出异常来中断程序。

scala.util.control.Breaks.breakable {
            for ( i <- 1 to 5 ) {
                if ( i == 3 ) {
                    scala.util.control.Breaks.break
                }
                println(i)
            }
        }

面向对象编程

 面向对象编程基础

 包

Scala中的基本的package的语法和Java完全一致。

package 包名

扩展语法
①Scala中的包和类的物理路径没有关系

②package关键字可以嵌套声明使用

③子包可以直接访问父包中的内容,而无需import

④Scala中package也可以看作对象,并声明属性和函数。可以将一个包中共通性的方法或属性在包对象中声明。那么这个包中的所有的类都可以直接访问这个包对象。

 导入

Scala中基本的import导入语法和Java完全一致。

import 类名

扩展语法
①Scala中使用下划线代替java中的 * 。eg: import java.util._

②scala中默认导入的类: java. lang包中所有的类、scala包中的类、Predef (类似 java中静态导入)

③Scala中的import语法可以在任意位置使用

④Scala中可以导包,而不是导类

⑤Scala中可以在同一行中导入多个类,简化代码

⑥Scala中可以屏蔽某个包中的类

import java.sql.{ Date=>_, Array=>_}   //屏蔽sql中的Date、Array
⑦Scala中可以给类起别名,简化使用。eg: import java.util.{ArrayList=>AList}

Scala中有伴生类和伴生对象之分。

​ class修饰的类就是普通的伴生类,在使用时需要new对象。而Object用于修饰伴随着这个类所产生的一个单例对象,用于模仿java中的静态语法。object中的方法和属性都可以通过类名直接访问,类似于静态语法。

 属性

类的属性就是类变量。在声明的时候,必须进行初始化。也可以使用下划线进行属性的初始化,但是必须明确属性的类型,使用下划线进行初始化的属性一般声明为val的,后面可能要对这个属性进行更改。

​ Scala中的属性其实在编译后也会生成方法

val name = "HelloWorld"
 
//编译后的结果
final String name = "HelloWorld";
public String name() {
         return this.name;
}
public void name_$eq(final String x$1) {
         this.name = x$1;
}

 Scala为了迎合Java中的get和set方法,在Scala要想使用get和set方法,需要添加特殊的注解@BeanProperties,添加注解的不能设置为private的

 访问权限

private : 私有访问权限:同类

private[包名]: 包访问权限 --> 包可以向上使用:同类,同包, 包名只能跟本包有关系

protected : 受保护权限 : 同类,子类

(default) : 公共访问权限

方法

方法其实就是函数。

​ 但是伴生类中的私有的方法和属性,在其伴生对象中也可以使用。所以当类中的构造器私有化的时候,可以在伴生对象中创建apply方法,通过伴生对象来创建类的对象,在调用时,scala会自动识别apply方法,所以apply方法名可以省略。

​ 伴生对象只能初始化一次,所以通过伴生对象来创建对象是线程安全的。

​ apply主要用来构建对象,不一定是当前类的对象。apply可以重载。

object ScalaMethod{
    def main(args: Array[String]): Unit = {
        val user = new User  //通过new来创建User 的对象
        user.login("zhangsan", "000000")
 
        val user2 = User.apply()  //通过伴生类创建对象,
        val user3 = User() // 必须加上小括号,若不加小括号,则user3就是User伴生对象
    }
}
class User {
    def login( name:String, password:String ): Boolean = {
        false
    }
}
 
object User{  //User 的伴生对象,静态,可以通过类名直接访问,只会初始化一次
   def apply():User={   //不能省略小括号
           new User()
   }
}

小知识点:

  • 重写和重载

方法重载

  • 多个方法名称相同,但是参数列表(参数个数,参数类型,参数顺序)不相同
  • 参数为数值类型,在进行方法重载时,若参数类型符合,则直接调用对应的方法,若无对应的参数类型,则会提高精度。
  • Byte a = 1
    fun(a)  //由于没有Byte的类型,故进行精度提升,调用参数类型为Int的方法。
    def fun(n:Int)={}
    def fun(n:Long)={}
     引用类型,在重载的方法如果找不到对应的类型。会从类树往上查找

    方法重写

    方法的重写一定要存在父子类
    子类重写父类的方法。子类重写父类相同方法的逻辑
    方法名一致,参数列表保持一致
    既然父类和子类有相同的方法,形成了方法的重写
    那么在调用时,无法确定到底执行哪一个方法, 那么需要遵循动态绑定机制
    动态绑定机制:程序执行过程,如果调用了对象的“成员”“方法”时会将方法和对象的实际内存进行绑定,然后调用
    动态绑定机制和属性无关

  • 构造方法

  • Scala中类其实也是一个函数,类名其实就是函数名,类名后面可以增加括号,表示函数参数列表。这个类名所代表的函数其实就是主构造方法,构造方法执行时,会完成类的主体内容的初始化。

    ​ scala中提供了2种不同类型的构造方法。
    ​ ①主构造方法:在类名后的构造方法, 可以完成类的初始化

    ​ ②辅助构造方法:为了完成类初始化的辅助功能而提供的构造方法。声明方式为: def this0

    在使用辅助构造方法时,必须直接或间接地调用主构造方法。

    ​ Scala中一般构造方法的参数用于属性的初始化,所以为了减少数据的冗余,可以使用关键字var, val将构造参数当成类的属性来

    class User() { // 主构造函数 ,形参中可以添加var、val将形参作为类的属性直接使用
        var username : String = _ 
        def this( name:String ) { // 辅助构造函数,使用this关键字声明
            this() // 辅助构造函数应该直接或间接调用主构造函数
            username = name
        }
        def this( name:String, password:String ) {
            this(name) // 构造器调用其他另外的构造器,要求被调用构造器必须提前声明
        }
    }

     面向对象进阶

  • 继承

  • 跟Java一样,使用extends关键字表示类的继承关系。

    抽象

  • 抽象方法:不完整的方法,可以不使用abstract关键字

    ​ 若类中含有抽象方法/抽象属性,则此类必须为抽象类,用abstract关键字进行声明。

    ​ 抽象类中可以有完整的方法,若子类重写父类的完整方法,必须要用override关键字进行修饰。子类实现父类的抽象方法,可以使用或者不用override关键字。

    ​ 抽象属性:没有初始化的属性。

    ​ 子类重写父类的完整属性必须是val的,不能重写var的属性,实现抽象属性则没有要求。重写抽象属性,相当于普通属性的声明,这个属性可以是val和var的,可以使用或者不用override关键字。但是重写普通属性,只能是val的,必须要用override关键字进行修饰。

    特质

  • scala中没有接口。但是增加了特质(trait)。scala可以将多个类中相同的特征,从类中剥离出来,形成特殊的语法"特质"。特质中可以声明抽象方法,也可以声明普通方法。特质的使用需要混入到类中。特质的一个重要的功能:可以进行功能的扩展。

    ​ 特质也可以看做抽象类,继承其他的类,并用with混入其他的特质。特质又可以使用extends,又可以使用with。

    ​ java中所有的接口在scala中当成特质使用

  • 基本语法

    trait 特质名称{   //特质的声明
        方法
    }
    class 类名 extends 父类(特质1) with 特质2 with特质3   //类中混入多个特质
    new 类 with 特质1 with 特质2  //动态混入特质

    如果类混入多个特质,那么特质的初始化顺序为从左到右

    类混入多个特质的时候,功能的执行顺序从右向左

    特质中的super其实有特殊的含义,表示的不是父特质,而是上级特质。

    eg:注意理解super的含义。

    object ScalaTrait {
        def main(args: Array[String]): Unit = {
            val mysql: MySQL = new MySQL
            mysql.operData()  //功能执行,从右到左
        }
    }
     
    trait Operate{
        def operData():Unit={
            println("操作数据。。")
        }
    }
    trait DB extends Operate{
        override def operData(): Unit = {
            print("向数据库中。。")
            super.operData()
        }
    }
    trait Log extends Operate{
        override def operData(): Unit = {
            print(“hello”)
            super.operData()
        }
    }
    class MySQL extends DB with Log {
     
    }
    最终结果:hello向数据库中。。操作数据。。

    集合

    Scala的集合有三大类:序列Seq、集Set、映射Map。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。

  •  数组

  • 不可变数组
  • Array为不可变数组,Array可以通过new的方式创建数组,也可以通过伴生对象创建。

    数组的遍历:arr.foreach(print)

    数组的合并:Array.concat(arr1, arr2)

    创建并填充指定数量的数组:Array.fill [Int] (5)(-1)

  •  可变数组
  • ArrayBuffer。

    数据增加: buffer.append(1,2,3,4)

    数据修改: buffer.update(0,5) //0表示索引 ;buffer(1) = 6

    数据删除:buffer.remove(2); buffer.remove(2,2)

    可变数组 -->不可变数组 : buffer.toArray
    将不可变数组转换为可变数组: array.toBuffer

  • Seq集合

  • 不可变List
  • List是抽象的,不能new,只能用伴生对象创建。

    空集合: val list2: List[Nothing] = List() 等同于Nil集合

    连接集合:List.concat(list3, list4)

    创建一个指定重复数量的元素列表: List.fill [String] (3)(“a”)

  •  可变List
  • ListBuffer。

    增加数据:append方法或者buffer1 :+ 5、buffer1 += 5

    可变集合转变为不可变集合: buffer.toList

    不可变集合转变为可变集合:list.toBuffer

  •  Set集合

  •  不可变Set
     可变Set
  • mutable.Set。

    可变Set创建:mutable.Set(1,2,3,4); new mutable.Set()

    增加数据:set1.add(5)

    添加数据,更新完成以后包含: set1.update(6,true)

    删除数据,更新完成以后不包含: set1.update(3,false)

    删除数据: set1.remove(2)

    遍历数据: set1.foreach(println)

Map集合

Map(映射)是一种可迭代的键值对(key/value)结构。所有的值都可以通过键来获取。Map 中的键都是唯一的。Map中的数据都是元组。

 不可变Map

创建: val map1 = Map( “a” -> 1, “b” -> 2, “c” -> 3)

添加数据: map1 +(“d” -> 4)

创建空集合: Map.empty

获取指定key的值: map1.apply(“c”)

获取可能存在的key值: val maybeInt: Option[Int] = map1.get(“c”)

获取可能存在的key值, 如果不存在就使用默认值: println(map1.getOrElse(“c”, 0))

可变Map

val map1 = **mutable.**Map( “a” -> 1, “b” -> 2, “c” -> 3 )

添加数据: map1.put(“d”, 4)

修改数据: map1.update(“a”,8)

删除数据: map1.remove(“a”)

Map可以转换为其他数据类型:map1.toSet、 map1.toList、map1.toSeq、map1.toArray

获取可能存在的key值, 如果不存在就使用默认值: println(map1.getOrElse(“c”, 0))

元组

在Scala语言中,我们可以将多个无关的数据元素封装为一个整体,这个整体我们称之为:元素组合,简称元组。有时也可将元组看成容纳元素的容器

创建元组,使用小括号: val tuple = (1, “zhangsan”, 30)

根据顺序号访问元组的数据:println(tuple._1)

迭代器: val iterator: Iterator[Any] = tuple.productIterator

根据索引访问元素: tuple.productElement(0)

​ 如果元组的元素只有两个,那么我们称之为对偶元组,也称之为键值对: val kv: (String, Int) = (“a”, 1)

常用方法

  • 常用方法
    object ScalaCollection{
        def main(args: Array[String]): Unit = {
            val list = List(1,2,3,4)
     
            // 集合长度
            println("size =>" + list.size)
            println("length =>" + list.length)
            // 判断集合是否为空
            println("isEmpty =>" + list.isEmpty)
            // 集合迭代器
            println("iterator =>" + list.iterator)
            // 循环遍历集合
            list.foreach(println)
            // 将集合转换为字符串
            println("mkString =>" + list.mkString(","))
            // 判断集合中是否包含某个元素
            println("contains =>" + list.contains(2))
            // 取集合的前几个元素
            println("take =>" + list.take(2))
            // 取集合的后几个元素
            println("takeRight =>" + list.takeRight(2))
            // 查找元素
            println("find =>" + list.find(x => x % 2== 0))
            // 丢弃前几个元素
            println("drop =>" + list.drop(2))
            // 丢弃后几个元素
            println("dropRight =>" + list.dropRight(2))
            // 反转集合
            println("reverse =>" + list.reverse)
            // 去重
            println("distinct =>" + list.distinct)
        }
    }
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        val list = List(1,2,3,4)
        val list1 = List(3,4,5,6)
 
        // 集合头
        println("head => " + list.head)
        // 集合尾
        println("tail => " + list.tail)
        // 集合尾迭代
        println("tails => " + list.tails)
        // 集合初始化
        println("init => " + list.init)
        // 集合初始化迭代
        println("inits => " + list.inits)
        // 集合最后元素
        println("last => " + list.last)
        // 集合并集
        println("union => " + list.union(list1))
        // 集合交集
        println("intersect => " + list.intersect(list1))
        // 集合差集
        println("diff => " + list.diff(list1))
        // 切分集合
        println("splitAt => " + list.splitAt(2))
        // 滑动 : 窗口
        println("sliding => " + list.sliding(2))
        // 滚动  有步长的滑动窗口
        println("sliding => " + list.sliding(2,2))
        // 拉链
        println("zip => " + list.zip(list1))
        // 数据索引拉链
        println("zipWithIndex => " + list.zipWithIndex)
    }
}
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        val list = List(1,2,3,4)
        val list1 = List(3,4,5,6)
 
        // 集合最小值
        println("min => " + list.min)
        // 集合最大值
        println("max => " + list.max)
        // 集合求和
        println("sum => " + list.sum)
        // 集合乘积
        println("product => " + list.product)
        // 集合简化规约
        println("reduce => " + list.reduce((x:Int,y:Int)=>{x+y}))
        println("reduce => " + list.reduce((x,y)=>{x+y}))
        println("reduce => " + list.reduce((x,y)=>x+y))
        println("reduce => " + list.reduce(_+_))
        // 集合简化规约(左)  简约的数据类型可以不一样 op: (B, Int) => B ,参数B和Int有关系,泛型
        println("reduceLeft => " + list.reduceLeft(_+_))
        // 集合简化规约(右)
        println("reduceRight => " + list.reduceRight(_+_))
        // 集合折叠
        /**
            fo1d方法存在两数柯里化,有2个参数列表
第一个参数列表中的参数=z : AI  【z为zero,表示数据的初始值】
第二个参数列表中的参数=> (AI, A1)=>A1
*/
        println("fold => " + list.fold(0)(_+_))
        // 集合折叠(左)
        println("foldLeft => " + list.foldLeft(0)(_+_))
        // 集合折叠(右)
        println("foldRight => " + list.foldRight(0)(_+_))
        // 集合扫描  类似于fold方法,会将之间计算的结果保留下来
        println("scan => " + list.scan(0)(_+_))
        // 集合扫描(左)
        println("scanLeft => " + list.scanLeft(0)(_+_))
        // 集合扫描(右)
        println("scanRight => " + list.scanRight(0)(_+_))
    }
}
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        val list = List(1,2,3,4)
 
        // 集合映射
        println("map => " + list.map(x=>{x*2}))
        println("map => " + list.map(x=>x*2))
        println("map => " + list.map(_*2))
        // 集合扁平化
        val list1 = List(
            List(1,2),
            List(3,4)
        )
        println("flatten =>" + list1.flatten)
        // 集合扁平映射
        println("flatMap =>" + list1.flatMap(list=>list))
        // 集合过滤数据
        println("filter =>" + list.filter(_%2 == 0))
        // 集合分组数据
        println("groupBy =>" + list.groupBy(_%2))
        // 集合排序
        println("sortBy =>" + list.sortBy(num=>num)(Ordering.Int.reverse))
        println("sortWith =>" + list.sortWith((left, right) => {left < right}))
    }
}

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值