Scala Array操作

摘自《快学Scala》

0.重点

  • 长度固定则使用Array,若长度有可能变化则使用ArrayBuffer
  • 提供初始值时不要使用new
  • 用()来访问元素
  • 用for(elem <- arr)来遍历元素
  • 用for(elem <- arr if …)… yield …来将原数组转为新数组
  • Scala数组和Java数组可以互操作;用ArrayBuffer,使用scala.collection.JavaConversions中的转换函数

1.定长数组

val nums = new Array[Int](10)//所有元素初始化为0
val a = new Array[String](10) 
// 10个元素的字符串数组,所有元素初始化为null
val s = Array("Hello","World")
// 长度为2的Array[String]——类型是推断出来的,已提供初始值就不需要new了

s(0) = "Goodbye"
//Array("Goodbye","World")
//使用()而不是[]来访问元素

在JVM中,Scala的Array以Java数组方式实现。示例中的数组在JVM中的类型为java.lang.String[].Int, Double 或其他与java中基本类型对应的数组都是基本类型数组。如Array(2,3,5,7,11)在JVM中就是一个int[]

2.变长数组:数组缓冲

对于长度需要变化的数组,Java有ArrayList,C++有Vector,Scala中有ArrayBuffer

import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
//或者new ArrayBuffer[Int]
//一个空的数组缓冲,准备存放数组

b += 1
//ArrayBuffer(1),用 += 在尾端添加元素

b += (1, 2, 3, 5)
// ArrayBuffer(1, 1, 2, 3, 5)
//在尾端添加多个元素,以括号包起来

b ++= Array(8, 13, 21)
//ArrayBuffer(1,1,2,3,5,8,13,21)
// 可以用 ++= 操作符追加任何集合
//但是不能 b++= 1 【错误】1不是集合类型

b.trimEnd(5)
//移除最后5个元素
//ArrayBuffer(1,1,2)

在ArrayBuffer的尾端添加或移除元素是一个高效的操作(”amortized constant time“,固定时间)。
在任意位置插入或移除元素时,效率较低——在那位置之后的元素都要被平移。如:

b.insert(2,6)
//ArrayBuffer(1,1,6,2)
b.insert(2,7,8,9)
//ArrayBuffer(1,1,7,8,9,6,2)
b.remove(2)
//ArrayBuffer(1,1,8,9,6,2)
b.remove(2,3)
//ArrayBuffer(1,1,2)
//第二个参数是要移除多少元素
2.Array和ArrayBuffer的转换
b.toArray
//Array(1,1,2)
b.toBuffer
//ArrayBuffer(1,1,2)

3.遍历Array和ArrayBuffer

在Java和C++中,数组和数组列表/向量有一些语法上的不同,Scala则更加统一。大多数时候,可以用相同的代码处理这两种数据结构。

for(i <- 0 until a.length)
    println(i + ":" +a(i))
until返回所有小于但不包括上限的数字。

0 until (a.length, 2)
//Range(0,2,4,...)

(0 until a.length).reverse
//Range(...,2,1,0)

for(elem <- a)
    println(elem)

4.数组转换

从一个数组(或数组转换)出发,以某种方式对它进行转换,这些转换动作不会修改原始数组,而是产生一个全新的数组。

val a = Array(2,3,5,7,11)
val result = for(elem <- a) yield 2*elem
//result是Array(4,6,10,14,22)

for(elem <- a if elem % 2 == 0) yield 2* elem
//对每个偶数元素翻倍,并丢弃奇数元素

另一种做法:

a.filter(_ % 2 == 0).map(2 * _)
//或者
a.filter{_ % 2 == 0}map{ 2 * _}
//给定一个整数的数组缓冲,移除第一个负数之外的所有负数。
//从数组缓冲中移除元素并不高效,把非负数值拷贝到前端比较好
var first = true
val indexes = 
for(i<-0 until a.length if first || a(i) >= 0)
    yield{
    if (a(i) < 0) first = false;//遇到第一个负数时置first = false,以后再遇到负数,根据 first||a(i)>=0 就直接跳过了
    i //i是下标
    }
for (j <- 0 until indexes.length) a(j) = a(indexes(j))
    a.trimEnd(a.length - indexes.length)

关键是,拿到所有的下标后一次处理完。

5.常用算法

Array(1,7,2,9).sum
//19 
//对ArrayBufffer同样适用

要使用sum方法,元素类型必须是数值类型

ArrayBuffer("Mary","had","a","little","lamb").max
//"little"

sorted方法将Array或ArrayBuffer排序并返回经过排序的Array或ArrayBuffer,这个过程不会修改原始版本

val b = ArrayBuffer(1,7,2,9)
val bSorted = b.sorted //b没有改变,bSorted是ArrayBuffer(1,2,7,9)

sortWith方法:

val bDescending = b.sortWith(_>_) //ArrayBuffeer(9,7,2,1)

可以直接对一个数组排序,但不能对数组缓冲排序:

val a = Array(1,7,2,9)
scala.util.Sorting,quickSort(a)
//a : Array(1,2,7,9)

mkString方法:

a.mkString(" and ")
//"1 and 2 and 7 and 9"
a.mkString("<", "," , ">")

与toString相比:

a.toString
//"[I@73e5"
//这里调用的是来自Java的没有意义的toString方法
b.toString
//"ArrayBuffer(1,7,2,9)"
//toString方法报告了类型,便于调试

7.多维数组

Double的二维数组类型为Array[Array[Double]]
ofDim方法:

val matrix = Array.ofDim[Double](3,4)
//3行4列,3*4
matrix(row)(column) = 42

//创建不规则数组,每行长度各不相同
val triangle = new Array[Array[Int]](10) //10行
for(i <- 0 until triangle.length)
    triangle(i) = new Array[Int](i+1)

8.与Java的互操作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值