[From] https://blog.csdn.net/gongxifacai_believe/article/details/81916659

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/gongxifacai_believe/article/details/81916659

1、Scala中的集合

Scala有一个非常通用丰富强大可组合的集合库;集合是高阶的,并拥有一大套操作方法。Scala的所有的集合类都可以在包 scala.collection 包中找到,其中集合类都是高级抽象类或特性。

Iterable[T] 是所有可遍历的集合,它提供了迭代的方法(foreach)。
Seq[T] 是有序集合。
Set[T]是数学上的集合(无序且不重复)。
Map[T]是关联数组,也是无序的。
Scala 集合类系统地区分了可变的和不可变的集合。
可变集合可以在适当的地方被更新或扩展,意味着你可以修改、添加、移除一个集合的元素。而不可变集合类,相比之下永远不会改变。不过,你仍然可以模拟添加移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。可变的集合类位于 scala.collection.mutable 包中,而不可变的集合位于 scala.collection.immutable.scala.collection 包中。集合既可以是可变的,也可以是不可变的。
官方文档:http://www.scala-lang.org/docu/files/collections-api/collections.html
所有集合组件图示如下:

2、Scala集合List和Set

Scala集合中的seq包含了:Range和ArrayBuffer以及List。这些组件区分了可变和不可变类型。
(1)创建list集合

val list = List(1,2,3,4,5)

(2)Scala中的list包含两个部分,head+tail或head+Nil
list.head 代表返回第一个元素,list.tail 代表返回一个不包含第一个元素的集合,Nil代表空的list集合。

val list2 = 1::Nil

注意集合的顺序,前面是元素后面是集合

val list3 = 2::list2

前面的元素就是新的list的head,后面的就是新的list的tail
(3)创建一个可变的list集合

val listBuffer = scala.collection.mutable.ListBufferInt

(4)添加元素

listBuffer += 2
listBuffer +=(3,4,5)
listBuffer ++= List(6,7,8)
listBuffer -= (4,7)

(5)list练习:指定前缀
需求:使用递归函数给list中的每个元素都加上指定的前缀,并且打印出加上前缀的元素。
注意:最后一个元素的时候它的tail就是Nil。

 def dtor(list: List[Int], pfix: String){
if(list != Nil){
println(pfix + list.head)
dtor(list.tail,pfix)
}
}

(6)set集合创建
不可变集合:

 val set = Set(1,2,3,4)

可变集合:

val s = scala.collection.mutable.Set(1,2)

添加元素:
不可变集合:+ ++ - –
可变集合:+= ++= -= --=

3、Scala集合Map与Tuple

(1)创建Map
创建一个不可变的Map:

val ages = Map(“Leo” -> 30, “Jen” -> 25, “Jack” -> 23)
ages(“Leo”) = 31

创建一个可变的Map:

val ages = scala.collection.mutable.Map(“Leo” -> 30, “Jen” -> 25, “Jack” -> 23)
ages(“Leo”) = 31

使用另外一种方式定义Map元素:

val ages = Map((“Leo”, 30), (“Jen”, 25), (“Jack”, 23))

创建一个空的HashMap:

val ages = new scala.collection.mutable.HashMap[String, Int]

(2)访问Map的元素
获取指定key对应的value,如果key不存在,会报错:

val leoAge = ages(“Leo”)
val leoAge = ages(“leo”)

使用contains函数检查key是否存在:

val leoAge = if (ages.contains(“leo”)) ages(“leo”) else 0

getOrElse函数:

val leoAge = ages.getOrElse(“leo”, 0)

(3)修改Map的元素
更新Map的元素:

ages(“Leo”) = 31

增加多个元素:

ages += (“Mike” -> 35, “Tom” -> 40)

移除元素:

ages -= “Mike”

更新不可变的map:

val ages2 = ages + (“Mike” -> 36, “Tom” -> 40)

移除不可变map的元素:

val ages3 = ages - “Tom”

(4)遍历Map
遍历map的entrySet:

for ((key, value) <- ages) println(key + ” ” + value)

遍历map的key:

for (key <- ages.keySet) println(key)

遍历map的value:

for (value <- ages.values) println(value)

生成新map,反转key和value:

for ((key, value) <- ages) yield (value, key)

(5)SortedMap和LinkedHashMap
SortedMap可以自动对Map的key的排序:

val ages = scala.collection.immutable.SortedMap(“leo” -> 30, “alice” -> 15, “jen” -> 25)

LinkedHashMap可以记住插入entry的顺序:

val ages = new scala.collection.mutable.LinkedHashMap[String, Int]
ages(“leo”) = 30
ages(“alice”) = 15
ages(“jen”) = 25

(6)Map的元素类型—Tuple
Map的每一个元素(key,value)就称作:tuple元组对
简单的Tuple定义:

val t = (“leo”, 30)

访问Tuple:

t._1

zip拉链操作:

val names = Array(“leo”, “jack”, “mike”)
val ages = Array(30, 24, 26)
val nameAges = names.zip(ages)
for ((name, age) <- nameAges) println(name + “: ” + age)

4、数组Array

在Scala中,Array代表的含义与Java中类似,也是长度不可改变的数组。此外,由于Scala与Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上是Java数组。例如字符串数组在底层就是Java的String[],整数数组在底层就是Java的Int[]。
(1)数组初始化后,长度就固定下来了,而且元素全部根据其类型初始化

val a = new ArrayInt
a(0)
a(0) = 1
val a = new ArrayString

(2)可以直接使用Array()创建数组,元素类型自动推断

val a = Array(“hello”, “world”)
a(0) = “hi”
val a = Array(“leo”, 30)

(3)数组元素求和

val a = Array(1, 2, 3, 4, 5)
val sum = a.sum

(4)获取数组最大值

val max = a.max

(5)对数组进行排序

scala.util.Sorting.quickSort(a)

(6)获取数组中所有元素内容

a.mkString
a.mkString(“, “)
a.mkString(“<”, “,”, “>”)

(7)toString函数

a.toString

5、数组ArrayBuffer

在Scala中,如果需要类似于Java中的ArrayList这种长度可变的集合类,则可以使用ArrayBuffer。
(1)如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类

import scala.collection.mutable.ArrayBuffer

(2)使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer

val b = ArrayBufferInt

(3)使用+=操作符,可以添加一个元素,或者多个元素。这个语法必须要谨记在心!因为spark源码里大量使用了这种集合操作语法!

b += 1
b += (2, 3, 4, 5)

(4)使用++=操作符,可以添加其他集合中的所有元素

b ++= Array(6, 7, 8, 9, 10)

(5)使用trimEnd()函数,可以从尾部截断指定个数的元素

b.trimEnd(5)

(6)使用insert()函数可以在指定位置插入元素,但是这种操作效率很低,因为需要移动指定位置后的所有元素。

b.insert(5, 6)
b.insert(6, 7, 8, 9, 10)

(7)使用remove()函数可以移除指定位置的元素

b.remove(1)
b.remove(1, 3)

(8)Array与ArrayBuffer可以互相进行转换

b.toArray
a.toBuffer

(9)使用for循环和until遍历Array / ArrayBuffer
until是RichInt提供的函数

for (i <- 0 until b.length)
println(b(i))

(10)跳跃遍历Array / ArrayBuffer

for(i <- 0 until (b.length, 2))
println(b(i))

(11)从尾部遍历Array / ArrayBuffer

for(i <- (0 until b.length).reverse)
println(b(i))

(12)使用“增强for循环”遍历Array / ArrayBuffer

for (e <- b)
println(e)

(13)toString函数

b.toString

6、数组操作

(1)使用yield和函数式编程转换数组
对Array进行转换,获取的还是Array

val a = Array(1, 2, 3, 4, 5)
val a2 = for (ele <- a) yield ele * ele

对ArrayBuffer进行转换,获取的还是ArrayBuffer

val b = ArrayBufferInt
b += (1, 2, 3, 4, 5)
val b2 = for (ele <- b) yield ele * ele

结合if守卫,仅转换需要的元素

val a3 = for (ele <- if ele % 2 == 0) yield ele * ele

(2)使用函数式编程转换数组(通常使用第一种方式)

a.filter(_ % 2 == 0).map(2 * _)
a.filter { _ % 2 == 0 } map { 2 * _ }

(3)算法案例:移除第一个负数之后的所有负数

  1. 算法一:
    构建数组:
val a = ArrayBufferInt
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)

每发现一个第一个负数之后的负数,就进行移除,性能较差,多次移动数组:

var foundFirstNegative = false
var arrayLength = a.length
var index = 0
while (index < arrayLength) {
if (a(index) >= 0) {
index += 1
} else {
if (!foundFirstNegative) { foundFirstNegative = true; index += 1 }
else { a.remove(index); arrayLength -= 1 }
}
}

2.  算法二:
重新构建数组:

val a = ArrayBufferInt
a += (1, 2, 3, 4, 5, -1, -3, -5, -9)

每记录所有不需要移除的元素的索引,稍后一次性移除所有需要移除的元素。该算法性能较高,数组内的元素迁移只要执行一次即可。

var foundFirstNegative = false
val keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield {
if (a(i) < 0) foundFirstNegative = true
i
}
for (i <- 0 until keepIndexes.length) { a(i) = a(keepIndexes(i)) }
a.trimEnd(a.length - keepIndexes.length)

[转] Scala 的集合类型与数组操作的更多相关文章

  1. Scala:集合类型Collection和迭代器

    http://blog.csdn.net/pipisorry/article/details/52902549 Scala Collection Scala 集合分为可变的和不可变的集合. 可变集合可 ...

  2. 【Swift学习】Swift编程之旅---集合类型之数组(六)

    swift提供了3种主要的集合类型,array,set,dictionary.本节介绍array. 数组是存储有序的相同类型的集合,相同的值可以多次出现在不同的位置. 注意: swift的Array类 ...

  3. [Swift]遍历集合类型(数组、集合和字典)

    Swift提供了三种主要的集合类型,称为数组,集合和字典,用于存储值集合. 数组是有序的值集合. 集是唯一值的无序集合. 字典是键值关联的无序集合. Swift中无法再使用传统形式的for循环. // ...

  4. c#重点[集合类型]异常,数组,集合ArrayList,List<>,hashTable,hashtable泛型(Dictionary)

    1.foreach[对一些数组或集合进行遍历] foreach(类型 变量名 in 集合对象){语句体} //定义一个数组 ,,,,, }; foreach(var i in sNum1) { Con ...

  5. Scala中集合类型与java中集合类型转换

    对于java中的集合元素并不能在scala中拿来就用的,需要进行相应的转换. 1. 转换规则如下 从下面可以看出,有些可以相互转换的,有些只能单向转换: scala.collection.Iterab ...

  6. Python集合类型的操作与应用

    Python集合类型的操作与应用 一.Python集合类型 Python中的集合类型是一个包含0个或多个数据项的无序的.不重复的数据组合,其中,元素类型只能是固定数据类型,如整数.浮点数.字符串.元组 ...

  7. Swift3.0P1 语法指南——集合类型

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

  8. redis数据类型-集合类型

    集合类型 在集合中的每个元素都是不同的,且没有顺序. 一个集合类型(set)键可以存储至多2 32-1个(相信这个数字对大家来说已经很熟悉了)字符串. 集合类型的常用操作是向集合中加入或删除元素.判断 ...

  9. PLSQL集合类型

    PLSQL集合类型   --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...

随机推荐

  1. BUILDING ANGULAR APPS USING FLUX ARCHITECTURE

    Flux is an architectural pattern based on unidirectional data flow. Although it is originated in the ...

  2. iOS7中的多任务II

    [推送唤醒(Remote Notifications)] 在iOS6和之前,推送的类型是很单一的,无非就是显示标题内容,指定声音等.用户通过解锁进入你的应用后,appDelegate中通过推送打开应用 ...

  3. GCT英语口语复试中的常见问题总汇

    英语口语复试中常见的问题: 1. Where do you come from? 2. What kind of landscape surrounds your hometown? 3. What ...

  4. sql语句语句中的正则查找

    举例: select tncl_id from tncl where tncl_id regexp'^0065'; 有一表,数据有10万多条,其中某列数据示例如下: 100000-200000-300 ...

  5. 20155318 2016-2017-2 《Java程序设计》第九学习总结

    20155318 2016-2017-2 <Java程序设计>第九学习总结 教材学习内容总结 学习目标 了解JDBC架构 掌握JDBC架构 掌握反射与ClassLoader 了解自定义泛型 ...

  6. java并发编程实战:第十四章----构建自定义的同步工具

    一.状态依赖性管理 对于单线程程序,某个条件为假,那么这个条件将永远无法成真 在并发程序中,基于状态的条件可能会由于其他线程的操作而改变 可阻塞的状态依赖操作的结构 acquire lock on o ...

  7. 自我介绍+github注册

    我是网络工程141的蒋易,学号是1413042018 个人兴趣:打篮球,打羽毛球,打游戏 github注册流程 id:Scorpio1 注册困难:1.刚开始网页没打开. 2.全英文的界面无法看懂,要查 ...

  8. Lucene 分页搜索实现

    Lucene中有两种分页查询方式 1.一次查询出大量数据,然后根据页码定位是哪个文档,其实就是暴力获取了 2.通过调用searchAfter来实现 我们都知道collect是lucene中对搜索到的文 ...

  9. wpf(怎么跨线程访问wpf控件)

    在编写代码时,我们经常会碰到一些子线程中处理完的信息,需要通知另一个线程(我这边处理完了,该你了). 但是当我们通知WPF的UI线程时需要用到Dispatcher. 首先我们需要想好在UI控件上需要显 ...

  10. ASP.NET MVC学习(一)

    这几天在学习asp.net mvc 一上来就被书中的什么依赖注入,什么单元测试搞的晕晕呼呼,根本就不理解,前天开始做书中的运动商店项目,一上来就遇到个大难题,书中的连接字符串的写法,跟以往在winfo ...