Scala学习日记 Day3

工作如何繁忙,生活如何糟心,至少求知的这一刻是我的…

前言

基于Scala 2.12.14。学的《Scala for the Impatient》,记录每天的笔记,有些名词看的英文,翻得未必准确。
适用对象:Java程序员。尽可能在短时间内建立起Java到Scala的转换,做到能看能写。实际上在学习一门语言,应当逐步抛弃掉固有成见,才能发现其中乐趣。人生苦短,别用Java:(逃。

今日重点

  • 定长数组
  • 不定长数组
  • 多维数组
  • 操作数组的方式

定长数组

// 长度为10的整数数组,初始化值为0
val foo = new Array[Int](10)
// 自定义初始化值,使用apply特性
val bar = Array(1, 2, 3)
// 同样赋值也可以用到apply特性
bar(0) = 4

在JVM中,Scala的定长数组的实现和Java是一致的。

不定长数组

Scala中不定长数组是ArrayBuffer,从功能上等同Java中的ArryayList。

import scala.collection.mutable.ArrayBuffer
// 等价于 val ab = new ArrayBuffer[Int]
val ab = ArrayBuffer[Int]()

ab += 1
// [1]

ab += (2, 3)
// [1, 2, 3]

// 使用++=合并任何集合(collection)
ab ++= Array(4, 5)
// [1, 2, 3, 4, 5]

ab.trimEnd(1)
// [1, 2, 3, 4]

// 转换为定长数组
val arr = ab.toArray

多维数组

建立一个多维数组:

// 二维数组,三行四列
val matrix = Array.ofDim[Int](3, 4)
// 访问第二行第三列
matrix(1, 2)

ofDim方法只有Array有。
建立一个多维不规则数组(忘了专有名词,只记得大学学过hhh,ragged arrays):

val ragged = new Array[Array[Int]](2)
for (i <- ragged.indices)
  ragged(i) = new Array[Int](i + 1)

数组操作

随机访问

ab.insert(2, 3)
// [1, 2, 3, 3, 4]
ab.insert(4, 5, 6]
// [1, 2, 3, 3, 4, 5, 6]
ab.remove(2)
// [1, 2, 3, 4, 5, 6]
ab.remove(4, 5)
// [1, 2, 3, 4]

遍历数组

在Scala中定长和不定长数组的遍历方式一致:

for (i <- ab) {
  println(i)
  // 复习一下插值器
  println(s"${i}")
}
// 这种循环方式等价于
for (i <- ab.indices) {
  // indices方法生成一个索引集合,可以对它执行reverse,就实现逆向循环了
  println(ab(i))
}
// 还等价于
for (i <- 0 until ab.length) {
  println(ab(i))
}
// 设定步长为2
for (i <- 0 until ab.length by 2) {
  println(ab(i))
}

处理数组

// 生成新的数组
// for/yield循环会创建与原集合相同类型的集合
val newAb = for (ele <- ab) yield 2 * ele

处理满足特定条件的元素:

val conditionAb = for (ele <- ab if ele / 2 == 0) yield 2 * ele

别忘了Scala是函数式编程的一门语言,那么也有对应的函数式编程的写法:

ab.filter(_ / 2 == 0).map(2 * _)

高效处理

假设我们需要去除一个集合中的特定元素,那么最直观的方法自然是遍历集合并判断是否删除该元素:

// 删除数组中的负数
var n = ab.length
var i = 0
while (i < n) {
  if (0 <= ab(i)) i += 1
  else { ab.remove(i); n -= 1 }
}

这种方式需要记录当前遍历数组的索引,以及每次删除都要移动中间元素。如果能一次性将要删除的元素标记出来,再挨个反向删除,能减少删除元素带来的移动元素:

// 记录要删除的元素索引,并一次性删除
val readyToRemove = for (i <- ab.indices if ab(i) < 0) yield i
for (i <- readyToRemove.reverse) ab.remove(i)

还有一种方法是记录下需要保留的元素到数组头部,接着裁剪数组:

val readyToCopy = for (i <- ab.indices if 0 <= ab(i)) yield i
for (j <- readyToCopy.indices) ab(j) = ab(readyToCopy(j))
ab.trimEnd(ab.length - readyToCopy.length)

大学倒还有细致研究过这些技巧,现在工作时反而不在意这些细节,程序和我有一个能跑就行,hhh。

通用算法

Scala为集合提供了许多便捷的算法,在绝大多数场景下,它们一般是较优或最优的算法,没有非功能要求就直接使用:

val sum = ab.sum
val max =ab.max
val sorted = ab.sorted
// 按指定排序方法排序,示例降序
val desc = ab.sortWith(_ > _)
// 快排,只能作用在定长数组上
import scala.util.Sorting.quickSort
quickSort(Array(3, 10, 1))

Scala还提供了便捷的将数组转换为String的方式,便于我们输出:

ab.mkString
// res12: String = 123

ab.mkString(", ")
// res13: String = 1, 2, 3

// 试试这个
ab.mkString("<", ",", ">")

// 对变长和定长数组分别执行toString呢?
ab.toString
// res14: String = ArrayBuffer(1, 2, 3)
Array(1, 2, 3).toString
// res15: String = [I@1bf8b5d9
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值