Scala入门系列(三):数组

Array

与Java的Array类似,也是长度不可变的数组,此外,由于Scala与Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上是Java数组。

注意:访问数组中元素使用()而不是Java中的 []

scala> val a = new Array[String](10)
a: Array[String] = Array(null, null, null, null, null, null, null, null, null, n
ull)
scala> val a = new Array[Boolean](10)
a: Array[Boolean] = Array(false, false, false, false, false, false, false, false
, false, false)
scala> a(0)
res15: Boolean = false
scala> val a = new Array[Int](10)
a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
scala> a(0) = 1

?
可以直接使用Array()创建数组,元素类型自动推断(如果类型不一致则为公共父类型

scala> val a = Array("Hello", "World")
a: Array[String] = Array(Hello, World)
scala> val a = Array("Sparks", 30)
a: Array[Any] = Array(Sparks, 30)

// 常见操作
scala> val a = Array(3,4,1,2,5,3)
a: Array[Int] = Array(3, 4, 1, 2, 5, 3)
scala> val sum = a.sum
sum: Int = 18
scala> val max = a.max
max: Int = 5
scala> scala.util.Sorting.quickSort(a)
scala> a
res35: Array[Int] = Array(1, 2, 3, 3, 4, 5)
scala> a.mkString
res36: String = 123345
scala> a.mkString(",")
res37: String = 1,2,3,3,4,5
scala> a.mkString("<",",",">")
res38: String = <1,2,3,3,4,5>
// Array的toString有些问题
scala> a.toString
res39: String = [[email protected]
scala> b.toString
res40: String = ArrayBuffer(1, 6, 7, 8, 9, 10)

?

ArrayBuffer

类似于Java中的ArrayList长度可变集合类

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val b = ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
// 使用+=添加一个或者多个元素,spark源码中大量使用!!!
scala> b += 1
res17: b.type = ArrayBuffer(1)
scala> b += (2,3,4,5)
res18: b.type = ArrayBuffer(1, 2, 3, 4, 5)
// 使用++=添加其他集合中的所有元素
scala> b ++= Array(6, 7, 8, 9, 10)
res19: b.type = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// trimEnd方法可以从尾部截断指定个数的元素
scala> b.trimEnd(5)
scala> b
res21: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)
// 使用insert()函数可以在指定位置插入一个或者多个元素,效率较低
scala> b.insert(5,6)
scala> b.insert(6, 7, 8, 9, 10)
scala> b
res24: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用remove()函数可以移除指定位置的一个或者多个元素
scala> b.remove(1)
res25: Int = 2
scala> b.remove(1, 3)
scala> b
res27: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 6, 7, 8, 9, 10)
// Array与ArrayBuffer互相转化
scala> b.toArray
res28: Array[Int] = Array(1, 6, 7, 8, 9, 10)
scala> a.toBuffer
res29: scala.collection.mutable.Buffer[Any] = ArrayBuffer(Sparks, 30)

?

遍历Array和ArrayBuffer

  1. 使用until是RichInt提供的函数
    for (i <- 0 until b.length)
    print(b(i))
  2. 跳跃遍历,步进长度
    for (i <- 0 until (b.length, 2))
    print(b(i))
  3. 从尾部遍历
    for (i <- (0 until b.length).reverse)
    println(b(i))
  4. 使用“增强for循环”遍历
    for (e <- b)
    println(e)

?

数组操作之数组转换

  1. 使用yield
scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> val a2 = for(ele <- a) yield ele*ele
a2: Array[Int] = Array(1, 4, 9, 16, 25)

scala> val a = ArrayBuffer(1,2,3,4,5)
a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)

scala> val a2 = for(ele <- a) yield ele*ele
a2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 4, 9, 16, 25)
  1. 使用函数式编程
    _ 表示通配符
  • a.filter(_ % 2 == 0).map(2 * _) (推荐方式)
  • a.filter{ _ % 2 == 0} map {2 * _}

?

实战:移除第一个负数之后的所有负数

// 构建数组
scala> val a = ArrayBuffer[Int]()
a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> a += (1,2,3,4,5,-1,-3,-5,-9)
res45: a.type = ArrayBuffer(1, 2, 3, 4, 5, -1, -3, -5, -9)

// 发现第一个负数之后的负数,就进行移除,性能较差,多次移动数组
var foundFirstNegative = false
var index = 0
while(index < a.length) {
  if (a(index) >= 0) {
    index += 1
  }
  else {
    if (!foundFirstNegative) {foundFirstNegative=true; index += 1}
    else { a.remove(index)}
  }
}

//检索出所有需要元素的下标,然后将所有需要的元素左移至数组左侧,删除右侧不需要的元素。
//改良版,性能较高
var foundFirstNegative = false
val vaildIndex = for (i <- 0 until a.length if (!foundFirstNegative || a(i) >= 0)) yield {
  if (a(i) < 0) foundFirstNegative = true
  i
}
for(i <- 0 until vaildIndex.length) {a(i) = a(vaildIndex(i))}
a.trimEnd(a.length - vaildIndex.length)
时间: 2024-10-29 04:04:38

Scala入门系列(三):数组的相关文章

[转]C# 互操作性入门系列(三):平台调用中的数据封送处理

传送门 C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C#互操作性入门系列(三):平台调用中的数据封送处理 C#互操作性入门系列(四):在C# 中调用COM组件 本专题概要 数据封送介绍 封送Win32数据类型 封送字符串的处理 封送结构体的处理 封送类的处理 小结 一.数据封送介绍 看到这个专题时,大家的第一个疑问肯定是--什么是数据封送呢?(这系列专题中采用假设朋友的提问方式来解说概念,就是希望大家带着问题

C# 互操作性入门系列(三):平台调用中的数据封送处理

好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------------------------------------------------------------------- C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C#互操作性入门系列(三):平台调用中的数据封

Xen入门系列三【Xen 管理工具 xm】

xm命令是管理Xen的最基本的工具,可以通过xm --help 来获得帮助. 1. 列出所有正在运行的虚拟操作系统 # xm list PS[1]:可缩写为 xm li2. 启动虚拟机 # 通过配置文件启动虚拟机 # xm create <ConfigFile> # 通过虚拟机名称启动虚拟机,虚拟机必需已存在 xm list 中 # xm start <DomainName> 参数说明: ConfigFile:虚拟机配置文件 DomainName: 虚拟机名称 PS[2]:很多教程

RxJava入门系列三,响应式编程

RxJava入门系列三,响应式编程 在RxJava入门系列一,我向你介绍了RxJava的基础架构.RxJava入门系列二,我向你展示了RxJava提供的多种牛逼操作符.但是你可能仍然没能劝服自己使用RxJava,这一篇博客里我将向你展示RxJava提供的其他优势,没准了解了这些优势,你就真的想去使用RxJava了. 异常处理 直到目前为止,我都没有去介绍onComplete()和onError()方法.这两个方法是用来停止Observable继续发出事件并告知观察者为什么停止(是正常的停止还是因

C语言快速入门系列(三)

C语言快速入门系列(三) 结构化的程序设计 -----------------------------------转载请注明出处:coder-pig 本节引言: 在前面的学习中,我们对C语言的基本语法进行了了解,可以暂时理解成我们学了单词; 现在要做得就是学语法,也就是算法;就是构成一个一个基本的程序! 在这一节中我们要学习的是C语言中的输入输出,以及程序的三种结构(顺序,选择,循环结构) 本节学习路线图: 正文: 1.字符输入/输出函数 2.格式输入/输出函数 跟前面的单个字符的输入输出不同,

mybatis入门系列三之类型转换器

mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名,java类属性类型-数据库字段类型 前面两个都容易设置,但是第三点要求经常会出现java类型和数据库的存储类型不一样, 例如java类型是String,数据库中存储的是char.varchar.text 对于一般常见的类型对应,mybatis已经内部包含了类型转换器,使String类型的java属性

ActiveMQ入门系列三:发布/订阅模式

在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点模式并用代码实例进行说明,今天就介绍下发布/订阅模式. 一.理论基础 发布/订阅模式的工作示意图: 消息生产者将消息(发布)到topic中,可以同时有多个消息消费者(订阅)消费该消息. 和点对点方式不同,发布到topic的消息会被所有订阅者消费. 当生产者发布消息,不管是否有消费者,都不会保存消息. 一定要先

Scala入门系列(十三):类型参数

引言 Scala中类型参数是什么呢?其实就类似于Java中的泛型.定义一种类型参数,比如在集合.类.函数中定义类型参数,然后就可以保证使用到该类型参数的地方就只能是这种类型,从而实现程序更好的健壮性.   泛型类 泛型类,顾名思义,其实就是在类的声明中,定义一些泛型类型,然后在类内部,比如field或method,就可以使用这些泛型类型. 使用泛型类,通常是需要对类中的某些成员,比如某些field和method中的参数或变量,进行统一的类型限制,这样可以保证程序更好的健壮性和稳定性. 在使用类的

ES6入门系列三(特性总览下)

0.导言 最近从coffee切换到js,代码量一下子变大了不少,也多了些许陌生感.为了在JS代码中,更合理的使用ES6的新特性,特在此对ES6的特性做一个简单的总览. 1.模块(Module) --Chrome测试不可用 在ES6中,有class的概念,不过这只是语法糖,并没有解决模块化问题.Module功能则是为了解决模块化问题而提出的. 我们可以使用如下方式定义模块: 11_lib.js文件内容 // 导出属性和方法 export var PI = 3.1415926; export fun