Scala 第一篇 基础篇

Scala 第一篇 基础篇

一、变量与常量

1、变量

创建变量:必须赋初值

1、可以不指定变量的具体类型如 var a = 5,则变量的类型由【首次】赋值的值类型决定且锁定。

2、若声明时已指定变量类型如 var a:String = "",则类型不可更改

scala 复制代码
var variableName[:Type] = V

2、常量

创建常量且初始化后,常量的类型和值都将锁定

scala 复制代码
val valName[:Type] = V

二、数据类型

1、数据基本类型概览

Any: 所有类型的超类(顶级类型)

AnyVal: 值类型的超类

AnyRef: 引用类型的超类

Unit: 无值,类似java中的void

Nothing: 所有类型的子类

Null: 表示null或空引用

2、元组的声明与使用

元组 TupleN[T1,...,TN] (复合类型)

T :泛型

N :1~22

():表示元组

元组类型表达:推荐 syntactic suger 语法糖

(String, Int) <=> Tuple2[String, Int]

二元组的声明和初始化

scala 复制代码
val tp2 = ("java", 88)	// 实际应用:最简语法
val tp2: (String, Int) = ("java", 88) // 初学推荐
val tp2: Tuple2[String,Int] = Tuple2("java", 88) //写全
scala 复制代码
val v1 = tp2._1		// 元组的使用,提取元组第一个值
val v2 = tp2._2
val it:Iterator[Any] = tp2.productIterator

注意:为避免冲突,须知()还可以表示:

  1. 数组下标提取 array(int)
  2. 方法的参数列表 method(p1,...,p2)

3、Range介绍和使用

Range 属于值类型的超类 AnyVal,表示一个连续的数字序列。

通过 to 方法或 until 方法创建

scala 复制代码
// >=1 && < 10
val r:Range = START until END by STEP 	// STEP缺省默认为1
val a:Range = 1 until 10 by 2			// 创建了一个半开范围,从 1 开始(包含 1),到 10 结束(不包含 10),步长为 2。
val r:Range = Range(start:Int,stop:Int,step:Int)

// >=1 && <=10
val r:Range = START to END by STEP 		// STEP缺省默认为1
val a:Range.Inclusive = 1 to 10 by 2	// 创建了一个闭合范围,从 1 开始(包含 1),到 10 结束(包含 10),步长为 2。
val a:Range.Inclusive = Range.Inclusive(start:Int,stop:Int,step:Int)

4、Option 类型的使用和设计

Option 是 Scala 中用来表示可能包含值或者不包含值的容器类型。通常用于避免空指针异常,因为它要求显式地处理可能为空的情况。

scala 复制代码
val opt: Option[Int] = Some(10) //将 opt 设置为包含整数值 10 的 Some
val rst = opt.getOrElse(0)
//使用 getOrElse 方法从 opt 中获取值,如果 opt 是 Some,则返回其中的值(这里是 10),如果是 None,则返回指定的默认值(这里是 0)。

函数的设计利用 Scala 中的 Option 类型,以一种更安全和更函数式的方式处理可能为空的情况。通过返回 Option 类型,明确地表达了可能存在结果和不存在结果的两种可能性,从而避免空指针异常等问题。

scala 复制代码
def add(a:Int,b:Int):Option[Int] = {
    val sum = a + b
    if(sum>100){
    	None
    }else{
    	Some(sum)
	}
}

5、类型别名

简化复杂的类型名称

scala 复制代码
type S = String		//用S代表String
var str:S = "henry"

三、运算符

跟Java,C++等没什么区别

txt 复制代码
赋值运算符: 	= += -= *= /= %=
算术运算符: 	+ - * / %			没有 ++ --
关系运算符: 	> >= < <= == !=
逻辑运算符: 	&& || !

四、程序逻辑

1、一切都是表达式

scala 复制代码
val expr = {}		//声明时执行
scala 复制代码
lazy val expr = {}	//惰性表达式  使用时执行

惰性表达式举例

scala 复制代码
// 定义一个类,表示从数据库加载的数据
class DatabaseData {
  // 模拟从数据库加载数据的耗时操作
  println("Loading data from database...")
  // 假设这里是实际的加载数据操作
  // 这里只是简单地打印一条消息表示加载完成
  println("Data loaded.")
}

// 创建一个对象,包含一个惰性求值的表达式
object Main {
  // 定义一个惰性求值的表达式,表示从数据库加载数据
  lazy val data = new DatabaseData

  def main(args: Array[String]): Unit = {
    println("Main method starts.")
    // 在主方法中使用数据
    println("Accessing data...")
    // 当访问 data 时,如果 data 还没有被初始化,则执行初始化操作
    println(data)
    // 再次访问 data,此时由于已经初始化过了,所以不会再次执行初始化操作
    println(data)
    println("Main method ends.")
  }
}

2、分支语句

if...else 语句
scala 复制代码
val x = 10
//正常写法
if (x > 10) {
  println("x 大于 10")
} else if (x < 10) {
  println("x 小于 10")
} else {
  println("x 等于 10")
}
//类三元运算符写法
val rst = if(x > 10) "x 大于 10" else "x 小于等于 10"
模式匹配(重点)

在 Scala 中,模式匹配中的条件守卫允许在模式匹配的基础上增加额外的条件判断。当模式匹配成功后,会检查守卫条件是否为真,只有条件为真时,才会执行相应的逻辑

  1. 数值

    scala 复制代码
    val dial = Random.nextInt(4)
    val rst = dial match {
    	case 0 => "余额"
        case 1 => "充值"
        case 2 => "活动"
        case 3 => "贷款"
        case _ => "未知"
    }
  2. 字符串与条件守卫

    scala 复制代码
    val content = "123456@qq.com"
    val rst = content match {
        case a if a.matches("\\w+@\\w{2,}\\.(com|cn)") => "email"
        case a if a.matches("1[3-9]\\d{9}") => "handset"
        case "NULL" => "nothing"
        case _ => "unknown"
    }
    println(rst)	//输出:email
    
    val day = "Monday"
    day match {
      case "Monday" => println("星期一")	//最后只调用此行输出:星期一
      case "Tuesday" => println("星期二")
      case "Wednesday" => println("星期三")
      case _ if day.startsWith("T") => println("星期二到星期五")
      case _ => println("其他")
    }
  3. 元组

    scala 复制代码
    val rst = (7,101) match {
        case (3,_) => (3,1)
        case (5,a) => if(a%2==0) (5,0) else (5,1)
        case _ => (0,0)
    }
  4. 列表

    scala 复制代码
    val rst = List(1,"hive",88) match {
        case List(id,"java",score:Int) => if(score>=60) ("java","pass") else ("java","fail")
        case _ => ("SKIP","NONE")
    }
  5. 类型

    scala 复制代码
    val rst = value match {
        case a:Int => ("int",a)
        case a:(Int,Int) => ("Tuple2",a)
        case a:String => ("String",a)
        case _ => ("Unknown",1)
    }
  6. 嵌套

    scala 复制代码
    val rst = (1,("java",67)) match {
        case (1,(sub:String,score:Int)) => (sub,score)
        case _ => ("UnknownFormat",1)
    }

3、循环语句

while循环
scala 复制代码
var i = 0
while (i < 5) {
  println(s"当前的值为: $i")
  i += 1
}
do while循环
scala 复制代码
var j = 0
do {
  println(s"当前的值为: $j")
  j += 1
} while (j < 5)
for 循环

有多种不同的用法和语法糖

scala 复制代码
// 基本的 for 循环
for (i <- 0 until 5) {
  println(s"当前的值为: $i")
}

// 带有条件的 for 循环
for (i <- 0 until 10 if i % 2 == 0) {
  println(s"偶数值为: $i")
}

// 嵌套的 for 循环
for (i <- 0 to 2; j <- 0 to 2) {
  println(s"($i, $j)")
}

五、集合

scala 支持运算符的重载
immutable 不可变集合包,mutable 可变集合包
默认导入不可变集合包

使用可变集合需要先import scala.collection.mutable,再通过 mutable.T 使用

常用集合:List、Set、Map、Array

scala 复制代码
import scala.collection.immutable.Set						// 导入具体类
import scala.collection.mutable._							// 导入包内所有类
import scala.collection.mutable.{ListBuffer,ArrayBuffer}	// 导入包内部分类

1、List

scala 复制代码
import scala.collection.immutable.List
import scala.collection.mutable.LiscalastBuffer //可以代替链表高效插删

List分组体验代码

scala 复制代码
val list = List(1, 2, 3, 4, 5, 6, 7)

val it: Iterator[List[Int]] = list.grouped(3)
println("按3个分组")
it.foreach(println)

println("滑动窗口,步长1")
val it2 = list.sliding(3, 1)
it2.foreach(println)

println("滑动窗口,步长2")
val it3 = list.sliding(3, 2)
it3.foreach(println)

println("排列组合,不考虑顺序问题")
val it4 = list.combinations(3)
it4.foreach(println)

println("分组,按模2不同分组")
val map = list.groupBy(a => a % 2)
map.foreach(println)

println("是否大于3分组")
val map2 = list.groupBy(a => a > 3)
map2.foreach(println)

输出结果

scala 复制代码
按3个分组
List(1, 2, 3)
List(4, 5, 6)
List(7)
滑动窗口,步长1
List(1, 2, 3)
List(2, 3, 4)
List(3, 4, 5)
List(4, 5, 6)
List(5, 6, 7)
滑动窗口,步长2
List(1, 2, 3)
List(3, 4, 5)
List(5, 6, 7)
排列组合,不考虑顺序问题
List(1, 2, 3)
List(1, 2, 4)
List(1, 2, 5)
List(1, 2, 6)
List(1, 2, 7)
List(1, 3, 4)
List(1, 3, 5)
List(1, 3, 6)
List(1, 3, 7)
List(1, 4, 5)
List(1, 4, 6)
List(1, 4, 7)
List(1, 5, 6)
List(1, 5, 7)
List(1, 6, 7)
List(2, 3, 4)
List(2, 3, 5)
List(2, 3, 6)
List(2, 3, 7)
List(2, 4, 5)
List(2, 4, 6)
List(2, 4, 7)
List(2, 5, 6)
List(2, 5, 7)
List(2, 6, 7)
List(3, 4, 5)
List(3, 4, 6)
List(3, 4, 7)
List(3, 5, 6)
List(3, 5, 7)
List(3, 6, 7)
List(4, 5, 6)
List(4, 5, 7)
List(4, 6, 7)
List(5, 6, 7)
分组,按模2不同分组scala
(1,List(1, 3, 5, 7))
(0,List(2, 4, 6))
是否大于3分组
(false,List(1, 2, 3))
(true,List(4, 5, 6, 7))

2、Set

scala 复制代码
import scala.collection.immutable.Set
import scala.collection.mutable.Set

Set 体验差&~、交&、并| 代码

scala 复制代码
// 可变集合
val set1 =  mutable.Set(1, 2, 3)
val set2 = mutable.Set(3, 4, 5)
// 不可变集合
val set3 = Set(3, 4, 5, 6)

println("交集")
val ints0 = set1 & set2      // 等价于set1.intersect(set2)
println(ints0)

println("并集")
val ints1 = set1 | set2     // 等价于set1.union(set2)
println(ints1)

println("差集")
val ints2 = set1 &~ set2    // 等价于set1.diff(set2)
println(ints2)scala

// 差集,前后影响数据类型
val ints3: mutable.Set[Int] = set1 &~ set3
val ints4: Set[Int] = set3 &~ set1

输出结果

scala 复制代码
交集
Set(3)
并集
Set(1, 5, 2, 3, 4)
差集
Set(1, 2)

3、Map

scala 复制代码
import scala.collection.immutable.Map
import scala.collection.mutable.Map

Map体验 += -= ++ 代码

scala 复制代码
// 创建一个可变的 Map
var map = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)

// 添加键值对
map += ("d" -> 1)
map += (("sss", 2), ("xxx", 3))
scala
// 移除键值对
map -= "sss"

// 使用 ++ 添加另一个 Map
map ++= Map("e" -> 5, "f" -> 6)
scala
// 输出结果
println(map)

输出结果

scala 复制代码
Map(e -> 5, xxx -> 3, b -> 2, d -> 1, a -> 1, c -> 3, f -> 6)

4、Array

scala 复制代码
import scala.Array
import scala.collection.mutable.ArrayBuffer

Array体验 += -= ++ 代码

scala 复制代码
// 创建一个可变的数组缓冲
val buffer = ArrayBuffer(1, 2, 3)

// 在尾部添加一个元素
buffer += 4

// 移除指定位置的元素
buffer -= 2scala

// 添加另一个数组缓冲的所有元素
buffer ++= ArrayBuffer(5, 6, 7)scala

// 输出结果
println(buffer)

输出结果

scala 复制代码
ArrayBuffer(1, 3, 4, 5, 6, 7)

备注:Array 和 List 是两种不同的集合类型,区别如下

  1. 可变性
  • Array 是可变的,可以修改其元素的值,并且可以改变数组的长度。
  • List 是不可变的,一旦创建后,就不能修改其元素或长度。如果需要添加、删除或修改元素,可以通过创建新的 List 实例来实现。
  1. 实现方式
  • Array 在底层是通过 Java 数组来实现的,它提供了快速的随机访问(通过索引)和可变性。
  • List 则是使用链表(Linked List)来实现的,每个元素都连接到下一个元素,因此访问和修改操作的效率较低,但对于添加和删除元素来说更加高效。
  1. 类型
  • Array 是一个包含固定大小元素的集合,元素类型可以是任意类型,甚至可以是不同类型。
  • List 是一个包含有序元素的集合,元素的类型相同,并且列表的长度可以动态增长或缩减。

六、函数

1、普通函数, 匿名函数

普通函数 :最常见的函数类型
匿名函数:也称为函数字面量或 Lambda 表达式,没有名称,直接定义在代码中

函数定义
scala 复制代码
// 普通函数 
def add(x: Int, y: Int): Int = {
  x + y
}
// 匿名函数
val add: (Int, Int) => Int = (x, y) => x + y
字符串插值函数

字符串插值函数属于 Scala 中的内置函数

字符串插值函数允许将变量、表达式或者其他字符串插入到字符串字面量中,形成一个新的字符串。

Scala 提供了三种常用的字符串插值函数

scala 复制代码
val str = s""			
val str = raw""			
val str = f""

s 插值器:用于字符串插值,允许在字符串中引用变量或表达式。

scala 复制代码
val name = "Alice"
val age = 30
val message = s"My name is $name and I am $age years old."
println(message)		// 输出:My name is Alice and I am 30 years old.

f 插值器:用于格式化字符串,类似于 C 语言中的 printf 函数。

scala 复制代码
val weight = 75.5
val bmi = f"$weight%.2f"
println(s"Your BMI is $bmi")	//输出:Your BMI is 75.50

raw 插值器:用于原始字符串,不会对字符串中的特殊字符进行转义。

scala 复制代码
val path = raw"C:\Users\node"
println(path)	//输出:C:\Users\node

2、高阶函数(重点)

接受函数作为参数或返回函数的函数。

scala 复制代码
def applyFunc(f: Int => Int, x: Int): Int = f(x)
柯里化函数

将多个参数列表转换为一系列函数调用,每次调用返回一个新的函数

scala 复制代码
def add(x: Int)(y: Int): Int = x + y

分析以下两个方法的区别

scala 复制代码
def func1(init:Int)(a:Int*):Int = init+a.sum 	// 函数作为返回类型
def func2(init:Int, a:Int*):Int = init+a.sum

func1func2 实现的功能是相同的,只是在参数列表的形式上有所不同。使用柯里化的形式可以使代码更加灵活,提高了函数的复用性和可读性。

函数作为参数传递的三种方式
scala 复制代码
val it = List(1, 2, 3, 4, 5, 6, 7)
def show(e:Int)=println(e)
it.foreach(show) 			// 【自定义】函数(重用) 		3
it.foreach(e=>println(e)) 	// 【自定义】函数(一次性)	   2
it.foreach(println) 		// 调用scala【已定义】函数	1

3、隐式参数,隐式函数

隐式函数作用:共用,简化

不建议使用太多,了解即可

场景一

scala 复制代码
// 当编译器在某个上下文中需要类型 Int 而实际提供的是类型 String 时,会查找适用的隐式转换函数并将字符串转换为整数。
implicit def str(a:String) = a.toInt

val a: Int = "100"
val sum: Int = a + 1
println(sum)

场景二

scala 复制代码
def sum(array: Array[Int])(implicit a: Int = 0) = if (array.sum < 0) a else array.sum

println(sum(Array(1, 2)))			// 3
println(sum(Array(1, 2, -4)))		// 0
println(sum(Array(1, 2, -4))(100))	// 100
scala 复制代码
def sum(array: Array[Int])(implicit a: Int) = if (array.sum < 0) a else array.sum
	
implicit val st: Int = 1000
println(sum(Array(1, 2, -4)))		// 1000

4、偏函数

只对输入的某些值定义的函数,而对其他值不进行定义。

scala 复制代码
// 定义一个偏函数,只处理偶数的情况
val evenNumber: PartialFunction[Int, String] = {
  case x if x % 2 == 0 => s"$x is even"
}

// 使用偏函数处理输入值
println(evenNumber(2))  // 输出 "2 is even"
println(evenNumber(3))  // 抛出 MatchError 异常,因为偏函数未定义输入值为奇数的情况

5、总结

一、命名参数:

1、理解:默认入参规则是按方法或函数的参数列表顺序传参

2、应用:按 "参数名=值" 格式可以不遵循原始参数列表顺序传参
二、参数缺省值(默认值)

1、语法:声明方法时可以通过类似 (a:Int=5,...) 形式给参数提供【默认值】

2、应用:带有默认值的参数,若需要传入的就是默认值,则可缺省
三、匿名函数:将函数作为方法参数传递

1、语法:(参数列表)=>{方法体}
四、高阶函数

1、现象:将函数作为方法参数或返回类型

2、应用:函数作为返回类型:柯里化
五、中置表达式

1、语法:var v = 左元素 函数 右元素

2、案例:var range = 1 to|until 10

3、注意:方法的参数【只有一个参数】才可以使用中置表达式
六、嵌套函数

1、语法:允许在一个函数内部声明一个函数,作用域限当前函数内部
七、隐式参数

1、语法:参数前添加 implicit 关键字

2、限制:只能是最后一个参数列表且独占一个参数列表,自动传入同类型隐式值,通常和柯里化配合使用
八、隐式函数

1、语法:声明函数时,在 def 前添加 implicit 关键字

2、使用:类型转换,类型增强

scala 复制代码
implicit def toInt(str:String)=str.toInt
val b:Int = "123"	// 隐式转换

implicit def bool(bool:Boolean) = if(bool) 1 else 0
val a:Int = false

九、闭包

1、概念:在函数内使用函数外定义的自由变量,则该函数即闭包

2、例如:

scala 复制代码
var a = 5
val add = (b:Int) => a+b

3、闭包能够捕获自由变量的变化,闭包对自由变量做出的改变闭包外亦可见(惰性处理:即函数执行后产生作用)

6、补充:下划线 _ 用途。

可以用于表示各种不同的语法元素,具体取决于上下文

通配符 :在模式匹配、参数列表、导入语句等中,下划线 _ 可以用作通配符,表示匹配任意值或任意参数。

scala 复制代码
val list = List(1, 2, 3)
list.foreach(_ => println("Hello")) // 使用下划线作为参数,表示忽略参数

占位符 :在部分应用函数、匿名函数等场景中,下划线 _ 可以作为占位符,表示一个参数的位置,类似于匿名函数中的参数。

scala 复制代码
val addOne: Int => Int = _ + 1	// 使用下划线作为参数占位符,表示参数
import package._				// 导全部包
case _							// default

部分应用函数 :在柯里化函数中,下划线 _ 可以用作占位符,表示对某个参数进行部分应用,生成一个新的函数。

scala 复制代码
def add(a: Int)(b: Int): Int = a + bscala
val addTwo: Int => Int = add(2)(_) // 使用下划线作为部分应用函数的占位符

// 基于下划线的简易传参语法:参数占位符,参数列表中每个参数可以使用一条下划线
def cal(func:(Int,Int)=>Int, a:Int*)={
    var sum = 0
    for (elem <- a) {
        sum = func(sum, elem)
    }
    sum
}
// 下面两种写法的效果相同
val rst = cal(_ + _, 1, 2, 3, 4, 5)
val rst = cal((a,b)=>a+b, 1, 2, 3, 4, 5)

占位符语法糖 :在某些情况下,下划线 _ 可以用作语法糖,简化代码书写。

scala 复制代码
val list = List(1, 2, 3)
val sum = list.reduce(_ + _) // 使用下划线作为占位符,简化参数的书写

七、数组方法(重点)

1、创建数组

scala 复制代码
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(2, 3, 4, 5)
val length = buffer.length      //获取长度。
val bool0 = buffer.isEmpty      //是否为空。
val bool1 = buffer.nonEmpty     //是否不为空。
val bool2 = buffer.forall(x => x > 3)    //是否所有元素都满足给定的条件。
val bool3 = buffer.exists(x => x < 3)    //是否存在满足给定条件的元素。
val bool4 = buffer.contains(3)           //是否包含指定的元素
val bool5 = buffer.containsSlice(Seq(1, 2, 3)) // 是否包含指定的子序列
val bool6 = buffer.startsWith(Seq(1, 2))       //是否以指定的子序列开头
val bool7 = buffer.endsWith(Seq(4, 5))   //是否以指定的子序列结尾

// 检查两个数组缓冲区是否具有相关性,即它们的对应位置的元素是否满足指定的关系。
val bool8 = buffer.corresponds(Seq(1, 2, 3))((a, b) => a == b * b)
// 检查两个数组缓冲区是否具有相同的元素,且元素在相同的位置上具有相同的值。
val bool9 = buffer.sameElements(Seq(1, 2, 3))
// 返回一个逆向的数组缓冲区
val reverse: ArrayBuffer[Int] = buffer.reverse

备注:

  • Seq 是一个 trait(特质),用于表示序列(Sequence)。序列是一个有序的集合,可以包含重复的元素。Seq 特质定义了一些常见的序列操作,例如获取元素、迭代、转换等。
  • Seq 特质有许多具体的实现类,其中一些常见的包括 ListVectorArrayBuffer 等。这些实现类提供了不同的性能和特性,以满足不同的使用场景。

2、基本操作

scala 复制代码
import scala.collection.mutable.ArrayBuffer

val buffer = ArrayBuffer(2, 3, 4, 5)
val length = buffer.length      //获取长度。
val bool0 = buffer.isEmpty      //是否为空。
val bool1 = buffer.nonEmpty     //是否不为空。
val bool2 = buffer.forall(x => x > 3)    //是否所有元素都满足给定的条件。
val bool3 = buffer.exists(x => x < 3)    //是否存在满足给定条件的元素。
val bool4 = buffer.contains(3)           //是否包含指定的元素
val bool5 = buffer.containsSlice(Seq(1, 2, 3)) // 是否包含指定的子序列
val bool6 = buffer.startsWith(Seq(1, 2))       //是否以指定的子序列开头
val bool7 = buffer.endsWith(Seq(4, 5))   //是否以指定的子序列结尾

// 检查两个数组缓冲区是否具有相关性,即它们的对应位置的元素是否满足指定的关系。
val bool8 = buffer.corresponds(Seq(1, 2, 3))((a, b) => a == b * b)
// 检查两个数组缓冲区是否具有相同的元素,且元素在相同的位置上具有相同的值。
val bool9 = buffer.sameElements(Seq(1, 2, 3))
// 返回一个逆向的数组缓冲区
val reverse: ArrayBuffer[Int] = buffer.reverse

3、查找,定位

scala 复制代码
import scala.collection.mutable.ArrayBuffer

val buffer = ArrayBuffer(2, 3, 4, 5, 4)
val index1 = buffer.indexOf(3)                      // 查找第一次出现的位置
val index2 = buffer.indexOfSlice(Seq(2, 3, 4))      // 查找	子序列第一次出现的位置
val index3 = buffer.indexWhere(x => x % 2 == 0)     //查找第一个满足条件的元素的位置。
val index4 = buffer.lastIndexOf(3)                  //查找最后一次出现的位置
val index5 = buffer.lastIndexOfSlice(Seq(2, 3, 4))  //查找最后一次出现的位置。
val index6 = buffer.lastIndexWhere(x => x % 2 == 0) //查找最后一个满足条件的元素的位置

4、数据拷贝,移植

scala 复制代码
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(2, 3, 4, 5, 4)
val items = buffer.clone()    // 创建并返回当前数组缓冲区的一个副本

//将当前数组缓冲区的所有元素复制到指定的可变缓冲区 buf 中。
val buf: mutable.Buffer[Int] = mutable.Buffer(1, 34)
val buf2: mutable.ArrayBuffer[Int] = ArrayBuffer(3, 4)
buffer.copyToBuffer(buf2)
buf2.foreach(println)

//将当前数组缓冲区的元素复制到指定的数组 array 中的指定位置,从索引 start 开始,复制长度为 len。
val array: Array[Int] = new Array(buffer.length)
buffer.copyToArray(array, start = 0, len = buffer.length)

5、添加

scala 复制代码
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer((2, 3), (4, 5), (1, 4))
buffer.append((1, 111), (2, 3))       // 将一个或多个元素追加到末尾
buffer.appendAll(Array((3, 113)))     //将一个集合中的所有元素追加到末尾

buffer.prepend((2, 112))              //将一个或多个元素插入到开头
buffer.prependAll(Array((4, 114)))    //将一个集合中的所有元素插入到开头

buffer.insert(2, (5, 115), (34, 3))   //在指定位置插入一个或多个元素
buffer.insertAll(3, Array((6, 116)))  //在指定位置插入一个集合中的所有元素

//++= 操作符可以将另一个集合的所有元素追加到当前数组缓冲区的末尾。
val combine: ArrayBuffer[(Int, Int)] = buffer ++= Seq((7, 117), (8, 118))
//:+ 操作符可以将一个元素追加到数组缓冲区的末尾,生成一个新的数组缓冲区。
val newBuffer1: ArrayBuffer[(Int, Int)] = buffer :+ (9, 119) :+ (1, 3)
//+: 操作符可以将一个元素添加到数组缓冲区的开头,生成一个新的数组缓冲区。
val newBuffer2: ArrayBuffer[(Int, Int)] = (10, 120) +: buffer

备注:

  • ++=:++:最终类型由左侧表达式的类型决定

6、删除

scala 复制代码
import scala.collection.mutable.ArrayBuffer

val buffer = ArrayBuffer(1, 3, 4, 4, 6, 19, 34, 22, 14, 23)

//删除指定的单个元素,返回一个新的数组缓冲区。
val left1: ArrayBuffer[Int] = buffer - 3

//删除指定集合中的所有元素,返回一个新的数组缓冲区。
val left2: ArrayBuffer[Int] = buffer -- Seq(1, 4)

buffer -= 1             //删除指定的单个元素。
buffer --= Seq(3, 5)    //从数组缓冲区中删除指定集合中的所有元素

val removedElement: Int = buffer.remove(1)  //删除指定位置上的元素,并返回被删除的元素
buffer.remove(1, 5)       //从指定位置开始删除指定数量的元素
buffer.clear()            //清空

val left3: ArrayBuffer[Int] = buffer.drop(3)       //删除前 size 个元素,并返回剩余的元素。
val left4: ArrayBuffer[Int] = buffer.dropRight(2)  //删除后 size 个元素,并返回剩余的元素
val left5: ArrayBuffer[Int] = buffer.dropWhile(x => x < 6) //从左侧开始删除满足条件的元素,直到遇到第一个不满足条件的元素,并返回剩余的元素

buffer.trimEnd(1)         //从数组缓冲区的末尾删除指定数量的元素
buffer.trimStart(1)       //从数组缓冲区的开头删除指定数量的元素
buffer.reduceToSize(3)    //削减数组缓冲区的容量,使其大小等于指定的大小。

val distinct: ArrayBuffer[Int] = buffer.distinct //去重

7、修改

scala 复制代码
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1, 3, 4, 4, 6, 19, 34, 22, 14, 23)
buffer.update(2, 555)     //修改指定下标的元素为新的元素
buffer.foreach(e => print(s"$e "))

//返回一个新的数组缓冲区,其中指定下标的元素被替换为新的元素。
val newBuffer: ArrayBuffer[Int] = buffer.updated(1, 222)

//  val after: ArrayBuffer[Int] = buffer.patch(from, seq, replaced)
// 从 from 开始,用指定的序列 seq 替换或插入元素,返回修改后的新数组缓冲区。
// 参数 replaced 控制替换或插入的行为:当 replaced = 0 时,表示插入;当 replaced > 0 时,表示替换;
// 如果 seq 为空且 replaced > 0,表示删除。
val after: ArrayBuffer[Int] = buffer.patch(0, Seq(2, 4), 0)

8、提取

scala 复制代码
val buffer = ArrayBuffer((1, 3), (4, 4), (6, 19), (34, 22), (14, 23))
val item1: (Int, Int) = buffer.apply(1)   //返回数组缓冲区中指定下标的元素。

// 定义默认函数,当索引超出范围时返回默认值
def defaultFunction(index: Int): (Int, Int) = (0, 0)
// 返回数组缓冲区中指定下标的元素,如果索引超出范围,则返回由函数 defaultFunction 计算的默认值。
val item2: (Int, Int) = buffer.applyOrElse(1, defaultFunction)

// 定义一个判断函数
def predicateFunction(element: (Int, Int)): Boolean = element._1 % 2 != 0
//返回数组缓冲区中满足条件的第一个元素的 Option 类型,如果没有满足条件的元素,则返回 None。
val opt: Option[(Int, Int)] = buffer.find(predicateFunction)
//返回一个新的数组缓冲区,其中包含数组缓冲区中满足条件的所有元素。
val remain1: ArrayBuffer[(Int, Int)] = buffer.filter(predicateFunction)
//返回一个新的数组缓冲区,其中包含数组缓冲区中不满足条件的所有元素。
val remain2: ArrayBuffer[(Int, Int)] = buffer.filterNot(predicateFunction)

// 定义偏函数,用于将元组的第一个元素乘以 2,且第二个元素大于 10 的元组保留下来
val partialFunction: PartialFunction[(Int, Int), (Int, Int)] = {
	case (x, y) if y > 10 => (x * 2, y)
}
// 使用偏函数 pf 对数组缓冲区中的元素进行映射和过滤,返回一个新的数组缓冲区。
val items: ArrayBuffer[(Int, Int)] = buffer.collect(partialFunction)
// 使用偏函数 pf 对数组缓冲区中的第一个符合条件的元素进行映射,返回一个 Option 类型,如果找到符合条件的元素,则返回 Some(result),否则返回 None。
val firstItem: Option[(Int, Int)] = buffer.collectFirst(partialFunction)

下接: Scala 第二篇 算子篇

相关推荐
哎呦没12 分钟前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_8576009515 分钟前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
一点媛艺3 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生4 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程5 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk6 小时前
Go-性能调优实战案例
开发语言·后端·golang