[转] Scala 的集合类型与数组操作
[From] 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)算法案例:移除第一个负数之后的所有负数
- 算法一:
构建数组:
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 的集合类型与数组操作的更多相关文章
- Scala:集合类型Collection和迭代器
http://blog.csdn.net/pipisorry/article/details/52902549 Scala Collection Scala 集合分为可变的和不可变的集合. 可变集合可 ...
- 【Swift学习】Swift编程之旅---集合类型之数组(六)
swift提供了3种主要的集合类型,array,set,dictionary.本节介绍array. 数组是存储有序的相同类型的集合,相同的值可以多次出现在不同的位置. 注意: swift的Array类 ...
- [Swift]遍历集合类型(数组、集合和字典)
Swift提供了三种主要的集合类型,称为数组,集合和字典,用于存储值集合. 数组是有序的值集合. 集是唯一值的无序集合. 字典是键值关联的无序集合. Swift中无法再使用传统形式的for循环. // ...
- c#重点[集合类型]异常,数组,集合ArrayList,List<>,hashTable,hashtable泛型(Dictionary)
1.foreach[对一些数组或集合进行遍历] foreach(类型 变量名 in 集合对象){语句体} //定义一个数组 ,,,,, }; foreach(var i in sNum1) { Con ...
- Scala中集合类型与java中集合类型转换
对于java中的集合元素并不能在scala中拿来就用的,需要进行相应的转换. 1. 转换规则如下 从下面可以看出,有些可以相互转换的,有些只能单向转换: scala.collection.Iterab ...
- Python集合类型的操作与应用
Python集合类型的操作与应用 一.Python集合类型 Python中的集合类型是一个包含0个或多个数据项的无序的.不重复的数据组合,其中,元素类型只能是固定数据类型,如整数.浮点数.字符串.元组 ...
- Swift3.0P1 语法指南——集合类型
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- redis数据类型-集合类型
集合类型 在集合中的每个元素都是不同的,且没有顺序. 一个集合类型(set)键可以存储至多2 32-1个(相信这个数字对大家来说已经很熟悉了)字符串. 集合类型的常用操作是向集合中加入或删除元素.判断 ...
- PLSQL集合类型
PLSQL集合类型 --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...
随机推荐
- MySql 8小时解决方案:proxool连接池
最近做的项目用的mysql数据库,前天挂在服务器上,昨天早晨上班一来,同事就说API数据接口访问不了了,我马上mstsc登陆服务器看,报错了.马上重启tomcat,结果还能正常运行,当时没管,今天过来 ...
- linux数据库备份
linux数据库备份 服务端启用二进制日志 如果日志没有启开,必须启用binlog,要重启mysql,首先,关闭mysql,打开/etc/my.cnf,加入以下几行: [mysqld] log-bin ...
- 好用的开关按钮——switchbutton
1.简介 GitHub地址:https://github.com/zcweng/SwitchButton gradle: repositories { mavenCentral() jcenter( ...
- 在TFS 2013的迭代视图中修改工作项数目限制
当TFS迭代中的工作项数目超过500时,在TFS的网页(Web Access)显示中就会出现红色警告提示"积压工作(backlog)中的项数超出配置的限制500.当前总数为529-.&quo ...
- Solr 从文件创建索引
http://blog.csdn.net/clj198606061111/article/details/21492457 http://wiki.apache.org/solr/Extracting ...
- Python 爬虫入门实例(爬取小米应用商店的top应用apk)
一,爬虫是什么? 爬虫就是获取网络上各种资源,数据的一种工具.具体的可以自行百度. 二,如何写简单爬虫 1,获取网页内容 可以通过 Python(3.x) 自带的 urllib,来实现网页内容的下载. ...
- Winform窗体改变语言类型的方式
Winform改变语言类型比较复杂,需要根据不同语言应用语言资源.而软件在进行语言切换时,需要将当前的UI文化线程引用对应的语言类型.常用的有三种方式,此处使用两种,对比发现其中的优缺点: /// & ...
- .Net MVC5路由机制与扩展
新建一个MVC项目启动后,首先访问的地址是http://localhost:xxx/Home/Index,这时候我们也明白因为在程序中有个叫做Home的控制器,并且在这个控制器下面有个叫做Index的 ...
- c# async 事物
上菜 async await 机制 确实便捷开发 多线程时 如何一致性如何保证呢? public async Task<ActionResult<IEnumerable<stri ...
- Java50道经典习题-程序7 处理字符串
题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数.分析:利用while语句,条件为输入的字符不为'\n'. import java.util.*; public class Pr ...