Scala基础知识

news2024/11/6 3:14:25

scala

1、scala简介

​ scala是运行在JVM上的多范式编程语言,同时支持面向对象和面向函数式编程。

2、scala解释器

要启动scala解释器,只需要以下几步:

  • 按住windows键 + r
  • 输入scala即可

在这里插入图片描述

  • 在scala命令提示窗口中执行:quit,即可退出解释器

3、scala的基本语法

3.1、声明变量

在scala中,可以使用val或者var来定义变量,语法格式如下:

val/var 变量标识:变量类型 = 初始值

其中

  • val定义的是不可重新赋值的变量
  • var定义的是可重新赋值的变量

[!NOTE]

  • scala中定义变量类型写在变量名后面
  • scala的语句最后不需要添加分号

问题:val 和 var修饰的变量有什么区别?

3.2、字符串

scala提供多种定义字符串的方式,将来我们可以根据需要来选择最方便的定义方式。

  • 使用双引号

    val/var 变量名 = “字符串”
    
  • 使用插值表达式

    val/var 变量名 = s"${变量/表达式}字符串"
    
  • 使用三引号

    val/var 变量名 = """字符串1
    字符串2"""    
    
3.3、数据类型
基础类型类型说明
Byte8位带符号整数
Short16位带符号整数
Int32位带符号整数
Long64位带符号整数
Char16位无符号Unicode字符
StringChar类型的序列(字符串)
Float32位单精度浮点数
Double64位双精度浮点数
Booleantrue或false

注意下 scala类型与Java的区别

[!NOTE]

  1. scala中所有的类型都使用大写字母开头
  2. 整形使用Int而不是Integer
  3. scala中定义变量可以不写类型,让scala编译器自动推断
3.3.1、scala类型层次结构

在这里插入图片描述

3.4、表达式
3.4.1、条件表达式

条件表达式就是if表达式,if表达式可以根据给定的条件是否满足,根据条件的结果(真或假)决定执行对应的操作。

scala条件表达式的语法和Java一样。与Java不一样的是,

[!NOTE]

  • 在scala中,条件表达式也是有返回值的
  • 在scala中,没有三元表达式,可以使用if表达式替代三元表达式
3.4.2、块表达式
  • scala中,使用{}表示一个块表达式
  • 和if表达式一样,块表达式也是有值的
  • 值就是最后一个表达式的值

问题

请问以下代码,变量a的值是什么?

scala> val a = {
     | println("1 + 1")
     | 1 + 1
     | }
3.5、循环

在scala中,可以使用for和while,但一般推荐使用for表达式,因为for表达式语法更简洁

3.5.1、for循环

语法

for(i <- 表达式/数组/集合) {
    // 表达式
}
3.5.2、嵌套for循环

使用for表达式,打印以下字符

*****
*****
*****

步骤

  1. 使用for表达式打印3行,5列星星
  2. 每打印5个星星,换行

参考代码

for(i <- 1 to 3; j <- 1 to 5) {print("*");if(j == 5) println("")}
3.5.3、while循环

scala中while循环和Java中是一致的

示例

打印1-10的数字

参考代码

scala> var i = 1
i: Int = 1

scala> while(i <= 10) {
     | println(i)
     | i = i+1
     | }
3.6、方法

语法

def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
    // 方法体:一系列的代码
}

[!NOTE]

  • 参数列表的参数类型不能省略
  • 返回值类型可以省略,由scala编译器自动推断
  • 返回值可以不写return,默认就是{}块表达式的值

示例

  1. 定义一个方法,实现两个整形数值相加,返回相加后的结果
  2. 调用该方法

参考代码

scala> def add(a:Int, b:Int) = a + b
m1: (x: Int, y: Int)Int

scala> add(1,2)
res10: Int = 3
3.6.1、方法参数

scala中的方法参数,使用比较灵活。它支持以下几种类型的参数:

  • 默认参数
  • 带名参数
  • 变长参数

默认参数

在定义方法时可以给参数定义一个默认值。

示例

  1. 定义一个计算两个值相加的方法,这两个值默认为0
  2. 调用该方法,不传任何参数

参考代码

// x,y带有默认值为0 
def add(x:Int = 0, y:Int = 0) = x + y
add()

带名参数

在调用方法时,可以指定参数的名称来进行调用。

示例

  1. 定义一个计算两个值相加的方法,这两个值默认为0
  2. 调用该方法,只设置第一个参数的值

参考代码

def add(x:Int = 0, y:Int = 0) = x + y
add(x=1)

变长参数

如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。

语法格式:

def 方法名(参数名:参数类型*):返回值类型 = {
    方法体
}

[!NOTE]

在参数类型后面加一个*号,表示参数可以是0个或者多个

示例

  1. 定义一个计算若干个值相加的方法
  2. 调用方法,传入以下数据:1,2,3,4,5

参考代码

scala> def add(num:Int*) = num.sum
add: (num: Int*)Int

scala> add(1,2,3,4,5)
res1: Int = 15
3.7、函数

语法

val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体

[!TIP]

  • 函数是一个对象(变量)
  • 类似于方法,函数也有输入参数和返回值
  • 函数定义不需要使用def定义
  • 无需指定返回值类型

示例

  1. 定义一个两个数值相加的函数
  2. 调用该函数

参考代码

scala> val add = (x:Int, y:Int) => x + y
add: (Int, Int) => Int = <function2>

scala> add(1,2)
res3: Int = 3

4、数据结构

4.1、数组

定长数组

  • 定长数组指的是数组的长度不允许改变
  • 数组的元素可以改变

语法

// 通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)

// 用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3...)

[!NOTE]

  • 在scala中,数组的泛型使用[]来指定
  • 使用()来获取元素

变长数组

创建变长数组,需要提前导入ArrayBuffer类import scala.collection.mutable.ArrayBuffer

语法

  • 创建空的ArrayBuffer变长数组,语法结构:

    val/var a = ArrayBuffer[元素类型]()
    
  • 创建带有初始元素的ArrayBuffer

    val/var a = ArrayBuffer(元素1,元素2,元素3....)
    

数组的相关操作

  • 使用+=添加元素
  • 使用-=删除元素
  • 使用++=追加一个数组到变长数组
  • 使用for遍历数组
4.2、元组

元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的。

语法

使用括号来定义元组

val/var 元组 = (元素1, 元素2, 元素3....)

使用箭头来定义元组(元组只有两个元素)

val/var 元组 = 元素1->元素2

示例

定义一个元组,包含一个学生的以下数据

id姓名年龄地址
1zhangsan20beijing

参考代码

scala> val a = (1, "zhangsan", 20, "beijing")
a: (Int, String, Int, String) = (1,zhangsan,20,beijing)

访问元组

使用_1、_2、_3…来访问元组中的元素,_1表示访问第一个元素,依次类推

示例

  • 定义一个元组,包含一个学生的姓名和性别,“zhangsan”, “male”
  • 分别获取该学生的姓名和性别

参考代码

scala> val a = "zhangsan" -> "male"
a: (String, String) = (zhangsan,male)

// 获取第一个元素
scala> a._1
res41: String = zhangsan

// 获取第二个元素
scala> a._2
res42: String = male
4.3、列表

不可变列表

语法

使用List(元素1, 元素2, 元素3, ...)来创建一个不可变列表,语法格式:

val/var 变量名 = List(元素1, 元素2, 元素3...)

使用Nil创建一个不可变的空列表

val/var 变量名 = Nil

使用::方法创建一个不可变列表

val/var 变量名 = 元素1 :: 元素2 :: Nil

[!TIP]

使用**::拼接方式来创建列表,必须在最后添加一个Nil

可变列表

可变列表就是列表的元素、长度都是可变的。

要使用可变列表,先要导入import scala.collection.mutable.ListBuffer

[!NOTE]

  • 可变集合都在mutable包中
  • 不可变集合都在immutable包中(默认导入)

定义

使用ListBuffer[元素类型]()创建空的可变列表,语法结构:

val/var 变量名 = ListBuffer[Int]()

使用ListBuffer(元素1, 元素2, 元素3…)创建可变列表,语法结构:

val/var 变量名 = ListBuffer(元素1,元素2,元素3...)

可变列表的操作

  • 获取元素(使用括号访问(索引值)
  • 添加元素(+=
  • 追加一个列表(++=
  • 更改元素(使用括号获取元素,然后进行赋值
  • 删除元素(-=
  • 转换为List(toList
  • 转换为Array(toArray
4.4、集合

Set(集)是代表没有重复元素的集合。Set具备以下性质:

  1. 元素不重复
  2. 不保证插入顺序

scala中的集也分为两种,一种是不可变集,另一种是可变集。

不可变集

语法

创建一个空的不可变集,语法格式:

val/var 变量名 = Set[类型]()

给定元素来创建一个不可变集,语法格式:

val/var 变量名 = Set(元素1, 元素2, 元素3...)

可变集

定义

可变集合不可变集的创建方式一致,只不过需要提前导入一个可变集类。

手动导入:import scala.collection.mutable.Set

4.5、映射

Map可以称之为映射。它是由键值对组成的集合。在scala中,Map也分为不可变Map和可变Map。

不可变Map

定义

语法

val/var map = Map(->,->,->...)	// 推荐,可读性更好
val/var map = Map((,), (,), (,), (,)...)

示例

1)定义一个映射,包含以下学生姓名和年龄数据

"zhangsan", 30
"lisi", 40

2)获取zhangsan的年龄

scala> val map = Map("zhangsan"->30, "lisi"->40)
map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30)

// 获取zhangsan的年龄
scala> val age = map.get("zhangsan")

可变Map

定义

定义语法与不可变Map一致。但定义可变Map需要手动导入import scala.collection.mutable.Map

示例

1)定义一个映射,包含以下学生姓名和年龄数据

"zhangsan", 30
"lisi", 40

2)修改zhangsan的年龄为20

scala> val map = Map("zhangsan"->30, "lisi"->40)
map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30)

// 修改value
scala> map("zhangsan") = 20

5、函数式编程

  • 遍历(foreach
  • 映射(map
  • 映射扁平化(flatmap
  • 过滤(filter
  • 是否存在(exists
  • 排序(sortedsortBysortWith
  • 分组(groupBy
  • 聚合计算(reduce
  • 折叠(fold

6、伴生对象

一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类

  • 伴生对象必须要和伴生类一样的名字
  • 伴生对象和伴生类在同一个scala源文件中
  • 伴生对象和伴生类可以互相访问private属性

参考代码

object _11ObjectDemo {

  class CustomerService {
    def save() = {
      println(s"${CustomerService.SERVICE_NAME}:保存客户")
    }
  }

  // CustomerService的伴生对象
  object CustomerService {
    private val SERVICE_NAME = "CustomerService"
  }

  def main(args: Array[String]): Unit = {
    val customerService = new CustomerService()
    customerService.save()
  }
}

7、样例类

样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类)

语法格式

case class 样例类名(var/val 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)
  • 如果要实现某个成员变量可以被修改,可以添加var
  • 默认为val,可以省略

需求

  • 定义一个Person样例类,包含姓名和年龄成员变量
  • 创建样例类的对象实例(“张三”、20),并打印它

参考代码

object _01CaseClassDemo {
  case class Person(name:String, age:Int)

  def main(args: Array[String]): Unit = {
    val zhangsan = Person("张三", 20)

    println(zhangsan)
  }
}

8、样例对象

它主要用在两个地方:

1)作为没有任何参数的消息传递

使用case object可以创建样例对象。样例对象是单例的,而且它没有主构造器

语法格式

case object 样例对象名

9、模式匹配

9.1、 简单模式匹配

语法格式

变量 match {
    case "常量1" => 表达式1
    case "常量2" => 表达式2
    case "常量3" => 表达式3
    case _ => 表达式4		// 默认配
}

示例

需求说明

1)从控制台输入一个单词(使用StdIn.readLine方法)

2)判断该单词是否能够匹配以下单词,如果能匹配,返回一句话

3)打印这句话

单词返回
hadoop大数据分布式存储和计算框架
zookeeper大数据分布式协调服务框架
spark大数据分布式内存计算框架
未匹配未匹配

参考代码

println("请输出一个词:")
// StdIn.readLine表示从控制台读取一行文本
val name = StdIn.readLine()

val result = name match {
    case "hadoop" => "大数据分布式存储和计算框架"
    case "zookeeper" => "大数据分布式协调服务框架"
    case "spark" => "大数据分布式内存计算框架"
    case _ => "未匹配"
}

println(result)
9.2、匹配样例类

scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。

示例

需求说明

  • 创建两个样例类Customer、Order
    • Customer包含姓名、年龄字段
    • Order包含id字段
  • 分别定义两个案例类的对象,并指定为Any类型
  • 使用模式匹配这两个对象,并分别打印它们的成员变量值

参考代码

// 1. 创建两个样例类
case class Person(name:String, age:Int)
case class Order(id:String)

def main(args: Array[String]): Unit = {
    // 2. 创建样例类对象,并赋值为Any类型
    val zhangsan:Any = Person("张三", 20)
    val order1:Any = Order("001")

    // 3. 使用match...case表达式来进行模式匹配
    // 获取样例类中成员变量
    order1 match {
        case Person(name, age) => println(s"姓名:${name} 年龄:${age}")
        case Order(id1) => println(s"ID为:${id1}")
        case _ => println("未匹配")
    }
}

10、高阶函数

高阶函数包含

  • 作为值的函数
  • 匿名函数
  • 闭包
  • 柯里化等等

作为值的函数

示例说明

将一个整数列表中的每个元素转换为对应个数的小星星

List(1, 2, 3...) => *, **, *** 

步骤

  1. 创建一个函数,用于将数字装换为指定个数的小星星
  2. 创建一个列表,调用map方法
  3. 打印转换为的列表

参考代码

val func = (num:Int) => "*" * num

println((1 to 10).map(func))

匿名函数

没有赋值给变量的函数就是匿名函数

参考代码

println((1 to 10).map(num => "*" * num))
// 因为此处num变量只使用了一次,而且只是进行简单的计算,所以可以省略参数列表,使用_替代参数
println((1 to 10).map("*" * _))

闭包

闭包其实就是一个函数,只不过这个函数的返回值依赖于声明在函数外部的变量。

可以简单认为,就是可以访问不在当前作用域范围的一个函数。

示例

定义一个闭包

val y=10

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

println(add(5)) // 结果15

add函数就是一个闭包

柯里化

柯里化(Currying)是指将原先接受多个参数的方法转换为多个参数列表的过程。

示例

示例说明

  • 编写一个方法,用来完成两个Int类型数字的计算
  • 具体如何计算封装到函数中
  • 使用柯里化来实现上述操作

参考代码

// 柯里化:实现对两个数进行计算
def calc_carried(x:Double, y:Double)(func_calc:(Double, Double)=>Double) = {
    func_calc(x, y)
}

def main(args: Intrray[String]): Unit = {
    println(calc_carried(10.1, 10.2){
        (x,y) => x + y
    })
    println(calc_carried(10, 10)(_ + _))
    println(calc_carried(10.1, 10.2)(_ * _))
    println(calc_carried(100.2, 10)(_ - _))
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1413293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线扫相机使用教程

一.线扫相机的采集原理 在现有的工业 2D 相机中&#xff0c;主要有两种类型的相机&#xff0c;面阵相机和线扫相机。这两种相机有其 各自的特点。 面阵相机&#xff1a;主要用于采集较小尺寸的产品&#xff0c;特别是长度方向较小的产品。其采集原理是通过 单次或多次曝光&…

nav02 学习03 机器人传感器

机器人传感器 移动机器人配备了大量传感器&#xff0c;使它们能够看到和感知周围的环境。这些传感器获取的信息可用于构建和维护环境地图、在地图上定位机器人以及查看环境中的障碍物。这些任务对于能够安全有效地在动态环境中导航机器人至关重要。 机器人的传感器类似人的感官…

蓝桥杯备战——7.DS18B20温度传感器

1.分析原理图 通过上图我们可以看到DS18B20通过单总线接到了单片机的P14上。 2.查阅DS18B20使用手册 比赛的时候是会提供DS18B20单总线通讯协议的代码&#xff0c;但是没有提供读取温度数据的代码&#xff0c;所以还是需要我们去查看手册&#xff0c;我只把重要部分截下来了 …

使用Spring Boot和Tess4J实现本地与远程图片的文字识别

概要&#xff1a; 在本文中&#xff0c;我们将探讨如何在Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字。我们将从添加依赖说起&#xff0c;然后创建服务类以实现OCR&#xff0c;最后展示如何处理…

用友移动管理系统 getApp SQL注入漏洞复现

0x01 产品简介 用友移动系统管理是用友公司推出的一款移动办公解决方案,旨在帮助企业实现移动办公、提高管理效率和员工工作灵活性。它提供了一系列功能和工具,方便用户在移动设备上管理和处理企业的系统和业务。 0x02 漏洞概述 用友移动管理系统 getApp 功能点未对用户的…

Hadoop增加新节点环境配置(自用)

完成Hadoop集群增添一个新的节点配置&#xff08;文中命名为&#xff09;Hadoop106&#xff0c;没有进行继续为该节点分配身份职能的步骤 1.在VMware中安装CentOS 7 新建虚拟机 1.⾸先我们创建⼀个新的虚拟机&#xff0c;也可以点⽂件-新建虚拟机。 2.选择⾃定义&#xff0c…

[C++]使用纯opencv部署yolov8旋转框目标检测

【官方框架地址】 https://github.com/ultralytics/ultralytics 【算法介绍】 YOLOv8是一种先进的对象检测算法&#xff0c;它通过单个神经网络实现了快速的物体检测。其中&#xff0c;旋转框检测是YOLOv8的一项重要特性&#xff0c;它可以有效地检测出不同方向和角度的物体。…

掌握可视化大屏:提升数据分析和决策能力的关键(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【CSS】字体效果展示

测试时使用了Google浏览器。 1.Courier New 2.monospace 3.Franklin Gothic Medium 4.Arial Narrow 5.Arial 6.sans-serif 7.Gill Sans MT 8.Calibri 9.Trebuchet MS 10.Lucida Sans 11.Lucida Grande 12.Lucida Sans Unicode 13.Geneva 14.Verdana 15.Segoe UI 16.Tahoma 17.…

PCB【基板】

1、fr4板是一种常用的绝缘基材&#xff0c;由玻璃纤维和环氧树脂组成【稳定性和耐温性、通信设备、消费电子和汽车电子、低功率电子产品】 2、铝基板&#xff0c;则是将铝合金作为基材【良好的导热性能、功率电子模块、高功率和高温环境】

(大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量

今天&#xff0c;面试了一家公司&#xff0c;什么也不说先来三道面试题做做&#xff0c;第一题。 那么&#xff0c;我们就开始做题吧&#xff0c;谁叫我们是打工人呢。 题目是这样的&#xff1a; 统计除豪车外&#xff0c;销售最差的车 车辆按批销售&#xff0c;每次销售若干…

【笔记】顺利通过EMC试验(16-41)-视频笔记

目录 视频链接 P1:电子设备中有哪些主要骚扰源 P2:怎样减小DC模块的骚扰 P3:PCB上的辐射源究竟在哪里 P4:怎样控制PCB板的电磁辐射 P5:多层线路板是解决电磁兼容问题的简单方法 P6:怎样处理地线上的裂缝 P7:怎样降低时钟信号的辐射 P8:为什么IO接口的处理特别重要 P9…

使用NVIDIA TensorRT-LLM支持CodeFuse-CodeLlama-34B上的int4量化和推理优化实践

本文首发于 NVIDIA 一、概述 CodeFuse&#xff08;https://github.com/codefuse-ai&#xff09;是由蚂蚁集团开发的代码语言大模型&#xff0c;旨在支持整个软件开发生命周期&#xff0c;涵盖设计、需求、编码、测试、部署、运维等关键阶段。 为了在下游任务上获得更好的精…

【idea打包】idea打包项目了,虽然出现BUILD SUCCESS,但是jar是个无法启动的jar

idea的打包问题 问题怎么解决解决后的样子运行成功的样子 问题 我执行打包命令后生成一个jar&#xff0c;但是在执行 java -jar 命令之后出现了一下的情况 打开jar包里面的MANIFEST.MF 里面是这样的 Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Built-By: WX…

【华为 ICT HCIA eNSP 习题汇总】——题目集10

1、以下哪个动态路由协议不能应用在 IPv6 网络中&#xff1f; A、IS-IS B、RIPng C、BGP4 D、OSPFv3 考点&#xff1a;路由技术原理 解析&#xff1a;&#xff08;A&#xff09; IS-ISv6 是在 IPv6 环境下&#xff0c;IS-IS 协议进行了相应的扩展和改进&#xff0c;以适应 IPv6…

LC 2846. 边权重均等查询

2846. 边权重均等查询 难度&#xff1a; 困难 题目大意&#xff1a; 现有一棵由 n 个节点组成的无向树&#xff0c;节点按从 0 到 n - 1 编号。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges &#xff0c;其中 edges[i] [ui, vi, wi] 表示树中存在一条位于节点 …

AI数字人-数字人视频创作数字人直播效果媲美真人

在科技的不断革新下&#xff0c;数字人技术正日益融入到人们的生活中。近年来&#xff0c;随着AI技术的进一步发展&#xff0c;数字人视频创作领域出现了一种新的创新方式——AI数字人。数字人视频通过AI算法生成虚拟主播&#xff0c;其外貌、动作、语音等方面可与真实人类媲美…

element-UI上传文件后valid提示不消失

问题描述&#xff1a;上传文件完成后&#xff0c;必填信息提示不消失 解决方法&#xff1a;在<el-form-item>标签添加show-message属性&#xff0c;字段为空时才显示提示信息 <el-form-item :prop"fileList" :show-message"!form.fileList || !form.f…

命令行启动Android Studio模拟器

1、sdk路径查看&#xff08;打开Android Studio&#xff09; 以上前提是安装的Android Studio并添加了模拟器&#xff01;&#xff01;&#xff01; 2、复制路径在终端进入到 cd /Users/duxi/Library/Android/sdk目录&#xff08;命令行启动不用打开Android Studio就能运行模拟…

C++逆向分析--虚函数(多态的前置)

先理解一件事&#xff0c;在intel汇编层面来说&#xff0c;直接调用和间接调用的区别。 直接调用语法&#xff1a; call 地址 硬编码为 &#xff1a;e8 间接调用语法: call [ ...] 硬编码为: FF 那么在C语法中&#xff0c;实现多态的前提是父类需要实现多态的成员…