1. 数组

1.1 定长数组

scala.Array 是定长的可变的索引型集合, JVM 中, Scala 的 Array 是以 Java 数组方式实现. String 对应 java.lang.String, Int, Double或其他与 Java 中基本类型对应数组都有基本类型数组, 比如说 Array(1, 2) 在 JVM 中就是一个 int[].

val arr1 = new Array[Int](10)
val arr2 = Array(1, 3)  // 调用apply方法
arr2(1)  // 3,  apply 方法
arr2(1) = 2  // 可以改变 Array 中的值 ,  update 方法

1.2 变长数组

scala.collection.mutable.ArrayBuffer 是变长的可变的索引型集合, 在 ArrayBuffer 的尾部添加和删除元素是一个高效的操作, 你也可以在任何位置插入或者移除元素, 但是这样的操作并不那么高效

import  scala.collection.mutable.ArrayBufferval b = ArrayBuffer[Int]()  // 或 val b = ArrayBuffer[Int]
b += 1  // += 在尾部添加元素  1
b += (2 ,3)  // += 尾部添加多个元素,  用括号括起来 1, 2, 3
b ++= Array(4, 5)  // ++= 用来追加任何集合 1 2 3 4 5b.trimEnd(2)  //  删除尾部2个元素; 1 2 3
b.trimStart(1)  // 删除头部2个元素 2 3b.insert(1, 4)  // 在下标1之前插入4;  2 4 3
b.insert(1, 6, 7)  // 在下标1之前插入6, 7;  2 6 7 4 3b.remove(2)  // 删除 b(2);  2 6 4 3
b.remove(2, 2)  // 删除 b.slice(2, 2+2);  2 6

如果你需要一个 Array, 但是不知道最终要装多少个元素, 你可以向使用 ArrayBuffer, 然后调用 b.toArray; 反过来你也可以使用 toBuffer 将数组转换为 ArrayBuffer

\(\color {red} {变长数组在 for 循环中有删除操作引发的不良后果}\)

scala> val ab = ArrayBuffer(1,2,3,4)
ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
scala> for (i<-0  until ab.size){if (ab(i) <3) ab.remove(i);println(ab)}
ArrayBuffer(2, 3, 4)
ArrayBuffer(2, 3, 4)
ArrayBuffer(2, 3, 4)
error: java.lang.IndexOutOfBoundsException: 3

1.3 遍历数组与数组转化

遍历数组

for ( i <- 0 until a.length)
for (i <- (0 until a.length).reverse)
for (elem <- a)

数组转换
利用 for (...) yield 循环会创建 一个类型和原始集合相同的集合的特点

val res = for(elem <- a if elem % 2 == 1)  yield 2 * elem   

上面的写法等价于

val res = a.filter(_ % 2 == 1).map(2 *_)

这里只是展示下 for 推导式在集合上的应用, 实际上, 在 Scala 中很少使用这种显示的循环结构, 更多的是利用函数来解决问题, 比如上面用到的 map 和 filter

1. 4 常用方法

val a = Array(1, 4, 3)  // 或 val a = ArrayBuffer(1, 4, 3)
a.sum  // 8
a.max  // 4
a.sortWith(_<_) // 1 3 4,  返回一个新集合,  a 并没有改变
scala.util.Sorting.quickSort(a)

下面看一下 toString 和 mkString方法

mkString 方法允许你指定元素之间的分隔符, 该方法的两个重载版本还可以指定前缀和后缀

val a = Array(2, 3)
val b = ArrayBuffer(2, 3)  scala> a.toString
res52: String = [I@52fa6742
scala> b.toString
res53: String = ArrayBuffer(2, 3)scala> a.mkString
res60: String = 23
scala> a.mkString(" and ")
res61: String = 2 and 3
scala> a.mkString("(",  ",", ")")
res62: String = (2,3)

从上面可以看出来, 如果是 Array 的话, 可以使用 mkString 方法将 Array 的内容打印到控制台

1. 5 多维数组

在 Scala中, 多维数组通过数组数组来实现. 比如说 Double 的二维数组类型为 Array[Array[Double]]

要构造这样的数组可以使用 ofDim 方法:

val ndim = Array.ofDim[Double](3, 4)

访问其中元素:
ndim(row)(column)

也可以自己创建一个不规则的数组

val triangle = new Array[Array[Int]](4)  // 4 是二维数组的行数
for (i <- 0 until triangle.length) {triangle(i) = new Array[Int](i + 1)
}

2. 元组

元组是不同类型的值的组合, 这些不同类型值包裹在在括号 ( ) 中; 和数组和字符串的不同, 元组的组元从1开始, 而不是 0, 你可以使用 _1, _2, ... 访问其组元; 可以通过模式匹配快速提取元组中的值.

 scala> val t = (1, 1.414,  "jerry")t: (Int, Double, String) = (1,1.414,jerry)scala>  t._1res18: Int = 1scala>  val (first, second, third) = tfirst: Int = 1second: Double = 1.414third: String = jerryscala> val (first, _, _) = t  // 如果只是需要使用第一个组元, 可以在不需要的位置使用 _first: Int = 1

3. 映射

有句经典的程序员名言, "如果只能有一种数据结构就用映射吧"

3.1 构造映射

Scala中, 映射是对偶的集合. 简单的说, 对偶就是2个值的元组, -> 操作符可以创建对偶, Scala会将 A->B 隐式转换为2元组 (A,B). 使用 -> 操作符只是因为 -> 更加符合人们对映射的直观感.

Scala 默认选择不可变映射, scala.collecton.immutable.Map, 如果你想要一个可变映射, 使用 scala.collecton.mutable.Map; 如果你想从一个空映射开始, 你需要指定映射的实现以及类型参数(可变与不可变都不可以直接 new Map[k, v]).

scala> val iage = Map("tom"->3, "jerry"->4)
iage: scala.collection.immutable.Map[String,Int] = Map(tom -> 3, jerry -> 4)scala> val age =  scala.collection.mutable.Map(("tom",3), ("jerry"->4))
age: scala.collection.mutable.Map[String,Int] = Map(tom -> 3, jerry -> 4)scala> val m1 = new Map[Int, Int]
<console>:15: error: trait Map is abstract; cannot be instantiatedscala> val m2 = new scala.collection.mutable.HashMap[Int, Int]
m2: scala.collection.mutable.HashMap[Int,Int] = Map()

已排序映射

在操作映射时, 你需要指定一个实现, 哈希表或者一个平衡树, 默认是哈希映射. 如果你不仅有查找需求还有排序需求的话, 可以使用树形映射; Scala 2.12 中不可变树形映射和可变树形映射都有.

scala> val age = scala.collection.mutable.SortedMap("tom"->3, "jerry"->4)
age: scala.collection.mutable.SortedMap[String,Int] = TreeMap(jerry -> 4, tom -> 3)scala> val  iage = scala.collection.immutable.SortedMap("tom"->3, "jerry"->4)
iage: scala.collection.immutable.SortedMap[String,Int] = Map(jerry -> 4, tom -> 3)

3.2 获取映射中的值

获取映射值: 映射通过 () 表示法调用 apply 方法来查找某个键对应的值; 如果映射中不包含请求中使用的键, 会抛出异常, 可以通过 contains 方法检查映射是否包含某个键; 也可以使用 getOrElse 方法和 get 方法, get 方法返回一个 Option对象.

val tom = age("tom")  // 3
val kitty = age.getOrElse("kitty", -1)  // -1, 获取键对应值,  若键不存在,  返回传入值
val jerry = age.get("jerry")  // jerry

3.3 更新映射

在可变映射中, 你可以更新某个映射的值, 或者添加一个新的对偶, 方法是 映射(key) = value , 这会调用 update 方法; 如果 key 在映射中则更新, 不在映射中则添加;

对于不可变映射, 虽然你不能改变一个不可变映射, 不过你可以通过不可变映射创建一个新映射, 更新和添加对偶, 新映射也是不可变集合, 因为新映射和老的映射共享大部分结构, 这样创建新映射的效率会很高.

// 可变映射
age("tom") = 4   // age.update("tom",  4)
//  更新, 输出 scala.collection.mutable.Map[String,Int] = Map(tom -> 4, jerry -> 4)age("kitty") = 5
// 添加, 输出 scala.collection.mutable.Map[String,Int] = Map(tom -> 4, kitty -> 5, jerry -> 4)// 不可变映射// 更新,  新映射也是不变的
var newAge = iage + ("tom"->64)
// 输出 scala.collection.immutable.Map[String,Int] = Map(tom -> 64, jerry -> 4)// 添加, 输出也可以看出来 iage 并没有改变,  tom ->3,
var newAge: scala.collection.mutable.Map[String,Int]  = iage + ("kitty"->6)
// 输出newAge: scala.collection.immutable.Map[String,Int] = Map(tom -> 3, jerry -> 4, kitty -> 6)

对于可变映射, 可以通过 += 操作符添加多个对偶, 要移除某个对偶使用 -=;

age += ("snow" -> 1, "dneyis"->3)
age -= "tom"  // 即使映射中没有 tom, 也不会报错

3.4 遍历映射

for ((k, v) <- 映射) yield (k, v)
for ((k, v) <- 映射) yield (v, k)  // 交换键和值的位置

这里通过模式匹配迭代获取映射中的对偶, 从而遍历了映射; Scala 中提供了方法来访问键和值

scala> age.keyS
keySet   keys   keysIteratorscala> age.values
values   valuesIterator

3.5 拉链操作

使用元组原因之一就是把多个值绑在一起, 以便它们能一起处理, 这通常用 zip 方法来完成. 比如说

val name = Array("tom", "jerry")
val age = Array(3 , 4)
val pairs = name.zip(age)  // pairs: Array[(String, Int)] = Array((tom,3), (jerry,4))

如果你有一个键的集合, 以及一个与之平行对应的值的集合, 那么你就可以用拉链操作将它们组合成一个映射了, 然后通过 Array 的 toMap 方法对偶的集合转换成映射, 最后结合 for ((k, v) <- 映射) yield statements, 这些对偶就可以被一起处理了

keys.zip(values).toMap
for ((k, v) <- 映射) yield statements

4. 排序

全部排序

下面引用 Scala 使用指南的例子说说集合该如何排序.

特质 Ordering 及其 on方法定义如下

trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializableon[U](f: (U) ⇒ T): Ordering[U]
Given f, a function from U into T, creates an Ordering[U] whose compare function is equivalent to:
def compare(x:U, y:U) = Ordering[T].compare(f(x), f(y))

Ordering 特质的伴生对象 Ordering 及其 by 方法定义如下

object Ordering extends LowPriorityOrderingImplicits with Serializabledef by[T, S](f: (T) ⇒ S)(implicit ord: Ordering[S]): Ordering[T]
Given f, a function from T into S, creates an Ordering[T] whose compare function is equivalent to:
def compare(x:T, y:T) = Ordering[S].compare(f(x), f(y))
This function is an analogue(类似物) to Ordering.on where the Ordering[S] parameter is passed implicitly.

on[U](f: (U) ⇒ T)
首先特质定义中 Ordering[T] 的 T 表明该特质用于 T 类型数据的排序. on 方法定义表明输入为 U 数据类型, 而 Ordering[T] 只能对 T 类型数据进行排序, 所以 on 方法接收 f: (U) ⇒ T 的函数, 然后对函数输出的 T 数据类型进行排序.

by[T, S](f: (T) ⇒ S)(implicit ord: Ordering[S])
Ordering 对象的 by 方法定义表明输入为 T 数据类型, 但是却要对 S 型数据排序, 所以需要能对 S 型数据排序的 Ordering[S], 故需要传入能对 S 型数据进行排序的Ordering[S]. 所以 by 方法接收 f: (T) ⇒ S 的函数, 然后对函数输出的 S 数据类型进行排序.

由于 Scala 具有自动类型推断的能力, 所以有时我们可以省略类型.下面看看例子吧

例子

import scala.util.Sorting
val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))// sort by 2nd element, [(String, Int, Int), Int] 是函数类型
// Ordering 为对象
Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))// sort by the 3rd element, then 1st
// Ordering[(Int, String)]为特质, 不省略类型即为
// Sorting.quickSort(pairs)(Ordering[(Int, String)].on[(String, Int, Int)](x => (x._3, x._1)))
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))

最大值

// 默认按照第一个排序
def max: A// 可以选择排序的元素
def maxBy[B](f: (A) ⇒ B): A

举个例子

scala> val arr = Array(("a", 5, 2), ("c", 2, 3), ("b", 3, 3))
scala> arr.max
res43: (String, Int, Int) = (c,2,3)scala> arr.maxBy(_._2)
res44: (String, Int, Int) = (a,5,2)scala> arr.maxBy(_._3)
res45: (String, Int, Int) = (c,2,3)scala> arr.maxBy(x=>(x._3,x._2))
res47: (String, Int, Int) = (b,3,3)

转载于:https://www.cnblogs.com/nowgood/p/Scala%e9%9b%86%e5%90%88%e5%85%a5%e9%97%a8.html

Scala 集合入门相关推荐

  1. 2021-08-26 转载 Scala快速入门系列博客文章

    作者:Huidoo_Yang 出处:http://www.cnblogs.com/yangp/ 本文版权归作者Huidoo_Yang和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面 ...

  2. Scala编程语言入门(3)

    文章目录 Scala编程语言入门 Scala进阶 trait特质 1. 作为接口使用 2. 定义具体方法 3. 定义具体方法和抽象方法 4. 定义具体字段和抽象字段 5. 实例对象混入 trait 模 ...

  3. Scala从入门到入土(从入门到放弃)

    Scala从入门到入土(从入门到放弃) 1 Scala介绍 Scala是一门 综合了 面向对象的 函数式编程的 基于JVm的 语言 特点: 1 语法简洁 2 开发速度快 , 运行速度快 3 兼容 Ja ...

  4. Scala编程语言入门(1)

    文章目录 Scala编程语言入门 Scala简介 搭建开发环境 安装JDK 安装 Scala SDK 安装IDEA的scala插件 scala的REPL交互式解释器 Scala语法基础 scala中声 ...

  5. 【Spark】scala基础入门

    文章目录 零.IDEA的scala环境配置 0.1 spark和scala之间的关系 0.2 编写项目 (0)创建项目 (1)配置pom.xml文件: (2)配置对应环境 (3)测试代码 (4)控制台 ...

  6. 3000门徒内部训练绝密视频(泄密版)第1课:大数据最火爆语言Scala光速入门

    大数据最火爆语言Scala光速入门 scala 可以使用java的库 scala 的工厂方法:apply 条件表达式有返回值 数组可以用to ,箭头 <- 最后一行内容的值是整个代码块的返回值 ...

  7. scala快速入门系列【偏函数】

    本篇作为scala快速入门系列的第三十一篇博客,为大家带来的是关于偏函数的内容. 文章目录 偏函数 定义 示例一 示例二 偏函数 偏函数提供了简洁的语法,可以简化函数的定义.配合集合的函数式编程,可以 ...

  8. Scala函数式编程(三) scala集合和函数

    前情提要: scala函数式编程(二) scala基础语法介绍 scala函数式编程(二) scala基础语法介绍 前面已经稍微介绍了scala的常用语法以及面向对象的一些简要知识,这次是补充上一章的 ...

  9. spark之scala快速入门

    scala和java都是在jvm之上的语言,相对来讲,scala热度比较低,其实并不是一个特别好的语言选择. 原因倒不是因为scala本身的缺点,而是使用人群不够多,论坛和社区不够活跃.这就跟社交软件 ...

最新文章

  1. 多继承的构造函数和析构函数
  2. python输出价目表-Python:使用基于事件驱动的SAX解析XML
  3. windows 10 python哪个版本的好-windows支持哪个版本的python
  4. 我的思维模式的阿喀琉斯之踵
  5. Nginx 负载均衡4种模式
  6. Jade之Extends
  7. 【HDU - 1301】Jungle Roads(并查集+最小生成树)(内附最小生成树两种算法 克鲁斯特尔算法amp;amp;普里姆算法)
  8. Oracle Logminer 说明
  9. 罗永浩回应被中消协点名;传前淘宝直播运营负责人因贪污被阿里通报;TypeScript 4.0 Beta发布​ | 极客头条...
  10. 回顾2020年(1)
  11. MongoDB 高阶
  12. 【日常计算机问题】装系统的烧录的U盘恢复方法
  13. autocad型源代码_autocad 二次开发的一些源码实例
  14. ubuntu10.10 教育网 使用ipv6,亲测可用【经过再次验证与修正】
  15. 支持2018的ibm服务器,联想支持Win10 2018年4月更新(RS4版本1803)的机型
  16. 华东师范大学计算机保研方案,经验分享:华东师范大学的成功保研之路(面试干货)...
  17. 笔记本电脑把BlackBerry当modem上网
  18. 如何在Windows中使用截图工具进行屏幕截图
  19. 冰蝎v4.0已经更新,在Java18下也能启动冰蝎。
  20. excel表格计算年龄_在Excel中计算年龄

热门文章

  1. 2022-2028年中国FEP薄膜行业市场发展规模及市场分析预测报告
  2. 2022-2028年中国蛋制品行业市场专项调查及前瞻分析报告
  3. 解决pip安装报错:is not a supported wheel on this platform
  4. Qt---布局,设置控件边距,拉伸因子
  5. 奇异值分解 SVD 的数学解释
  6. NVIDIA TensorRT高性能深度学习推理
  7. Android XML: unbound prefix
  8. android studio导入第三方库和demo
  9. leetcode-160-相交链表(simple)
  10. DS博客作业04--树大作业