数据结构

容器(Collection)

  • Scala提供了一套丰富的容器(collection)库,包括列表 (List)、数组(Array)、集合(Set)、映射(Map)等

  • 根据容器中元素的组织方式和操作方式,可以区分为有序 和无序、可变和不可变等不同的容器类别

  • Scala用了三个包来组织容器类,分别是scala.collection 、 scala.collection.mutable和scala.collection.immutable

  • 下图显示了scala.collection包中所有的容器类。这些都是 高级抽象类或特质。例如,所有容器类的基本特质(trait)是 Traverable特质,它为所有的容器类定义了公用的foreach 方法,用于对容器元素进行遍历操作

  • 下面的图表显示了scala.collection.immutable中的所有容器类

  • 下面的图表显示scala.collection.mutable中的所有容器类

列表(List)

  • 列表是一种共享相同类型的不可变的对象序列。既然是一个 不可变的集合, Scala的List定义在scala.collection.immutable包中

  • 不同于Java的java.util.List,scala的List一旦被定义,其值就 不能改变,因此声明List时必须初始化

scala> var strList = List("BigData","Hadoop","Spark")
strList: List[String] = List(BigData, Hadoop, Spark)
  • 列表有头部和尾部的概念,可以分别使用head和tail方法来获取

  • head返回的是列表第一个元素的值

scala> strList.head
res8: String = BigData
  • tail返回的是除第一个元素外的其它值构成的新列表,这体现出 列表具有递归的链表结构

scala> strList.tail
res9: List[String] = List(Hadoop, Spark)
scala> strList.tail.tail
res10: List[String] = List(Spark)
scala> strList.tail.tail.tail
res12: List[String] = List()
  • 构造列表常用的方法是通过在已有列表前端增加元素, 使用的操作符为::,例如:

scala> val strList = List("BigData","Hadoop","Spark")
strList: List[String] = List(BigData, Hadoop, Spark)
scala> val otherList = "Apache"::strList
otherList: List[String] = List(Apache, BigData, Hadoop, Spark)
scala> strList
res13: List[String] = List(BigData, Hadoop, Spark)
  • Scala还定义了一个空列表对象Nil,借助Nil,可以将 多个元素用操作符::串起来初始化一个列表

scala> val intList = 1::2::3::Nil
intList: List[Int] = List(1, 2, 3)
scala> val intList = List(1,2,3)
intList: List[Int] = List(1, 2, 3)

集合(Set)

  • 集合(set)是不重复元素的容器(collection)。列表中的元素 是按照插入的先后顺序来组织的,但是,“集合”中的元素并 不会记录元素的插入顺序,而是以“哈希”方法对元素的值 进行组织,所以,它允许你快速地找到某个元素

  • 集合包括可变集和不可变集,分别位于 scala.collection.mutable包和scala.collection.immutable 包,缺省情况下创建的是不可变集

scala> var mySet = Set("Hadoop","Spark")
mySet: scala.collection.immutable.Set[String] = Set(Hadoop, Spark)
scala> mySet += "Scala"
scala> mySet
res15: scala.collection.immutable.Set[String] = Set(Hadoop, Spark, Scala)

scala> val mySet = Set("Hadoop","Spark")
mySet: scala.collection.immutable.Set[String] = Set(Hadoop, Spark)
scala> mySet += "Scala"
<console>:9: error: value += is not a member of scala.collection.immutable.Set[String]
             mySet += "Scala"
                   ^
  • 如果要声明一个可变集,则需要提前引入scala.collection.mutable.Set

scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set
scala> val mySet = Set("Hadoop","Spark")
mySet: scala.collection.mutable.Set[String] = Set(Hadoop, Spark)
scala> mySet += "Scala"
res0: mySet.type = Set(Scala, Hadoop, Spark)
scala> mySet
res1: scala.collection.mutable.Set[String] = Set(Scala, Hadoop, Spark)

映射(Map)

  • 映射(Map)是一系列键值对的容器。在一个映射中,键是 唯一的,但值不一定是唯一的。可以根据键来对值进行快 速的检索

  • 和集合一样,Scala 采用了类继承机制提供了可变的和不 可变的两种版本的映射,分别定义在包 scala.collection.mutable 和scala.collection.immutable 里。 默认情况下,Scala中使用不可变的映射。如果想使用可 变映射,必须明确地导入scala.collection.mutable.Map

scala> val university = Map("XMU" -> "Xiamen University","THU" -> "Tsinghua University")
university: scala.collection.immutable.Map[String,String] = Map(XMU -> Xiamen University, THU -> Tsinghua University)
scala> university("XMU")
res3: String = Xiamen University
  • 对于这种访问方式,如果给定的键不存在,则会抛出异常, 为此,访问前可以先调用contains方法确定键是否存在

scala> val u = if (university.contains("XMU")) university("XMU") else 0
u: Any = Xiamen University
  • 不可变映射,是无法更新映射中的元素的,也无法增加新的 元素。如果要更新映射的元素,就需要定义一个可变的映射,也可以使用+=操作来添加新的元素

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala> val university2 = Map("XMU" -> "Xiamen University","THU" -> "Tsinghua University")
university2: scala.collection.mutable.Map[String,String] = Map(XMU -> Xiamen University, THU -> Tsinghua University)
scala> university2("XMU") = "xiamen university"//更新已有元素
scala> university2("FZU") = "Fuzhou university"//添加新元素
scala> university2
res6: scala.collection.mutable.Map[String,String] = Map(XMU -> xiamen university, THU -> Tsinghua University, FZU -> Fuzhou university)
scala> university2 += ("TIU" -> "Tianjin University")//添加新元素
res7: university2.type = Map(TIU -> Tianjin University, XMU -> xiamen university, THU -> Tsinghua University, FZU -> Fuzhou university)
循环遍历映射
  • 格式

for ((k , v) <- 映射) 语句块
scala> for ((k,v) <- university2) printf("Code is : %s and name is : %s\n" , k , v)
Code is : TIU and name is : Tianjin University
Code is : XMU and name is : xiamen university
Code is : THU and name is : Tsinghua University
Code is : FZU and name is : Fuzhou university
  • 或者,也可以只遍历映射中的k或者v

scala> for (k <- university2.keys) println(k)
TIU
XMU
THU
FZU

scala> for (v <- university2.values) println(v)
Tianjin University
xiamen university
Tsinghua University
Fuzhou university

迭代器(Iterator)

  • 在Scala中,迭代器(Iterator)不是一个集合,但是,提供了 访问集合的一种方法

  • 迭代器包含两个基本操作:next和hasNext。next可以返回迭 代器的下一个元素,hasNext用于检测是否还有下一个元素

scala> val iter = Iterator("Hadoop","Spark","Scala")
iter: Iterator[String] = non-empty iterator
scala> while(iter.hasNext){
    | println(iter.next())
    | }
Hadoop
Spark
Scala

scala> val iter = Iterator("Hadoop","Spark","Scala")
iter: Iterator[String] = non-empty iterator
scala> for (elem <- iter){
    | println(elem)
    | }
Hadoop
Spark
Scala
  • Iterable有两个方法返回迭代器:grouped和sliding。然而,这些迭代器返回的不是单 个元素,而是原容器(collection)元素的全部子序列。这些最大的子序列作为参数传 给这些方法。

  • grouped方法返回元素的增量分块,

  • sliding方法生成一个滑动元素的窗口。 两者之间的差异通过REPL的作用能够清楚看出。

scala> val list = List(1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> val iter = list grouped 3
iter: Iterator[List[Int]] = non-empty iterator
scala> iter.next()
res16: List[Int] = List(1, 2, 3)
scala> iter.next()
res17: List[Int] = List(4, 5)

scala> val sli = list sliding 3
sli: Iterator[List[Int]] = non-empty iterator
scala> sli.next()
res18: List[Int] = List(1, 2, 3)
scala> sli.next()
res19: List[Int] = List(2, 3, 4)
scala> sli.next()
res20: List[Int] = List(3, 4, 5)

数组(Array)

  • 数组是一种可变的、可索引的、元素具有相同类型的数据集合,它是各种高 级语言中最常用的数据结构。Scala提供了参数化类型的通用数组类Array[T], 其中T可以是任意的Scala类型,可以通过显式指定类型或者通过隐式推断来实例化一个数组。

scala> val arr = new Array[Int](3)
arr: Array[Int] = Array(0, 0, 0)
scala> arr(0) = 12
scala> arr
res24: Array[Int] = Array(12, 0, 0)
scala> arr(1) = 45
scala> arr(2) = 33
scala> arr
res27: Array[Int] = Array(12, 45, 33)

scala> val intArr = Array(12,45,23)
intArr: Array[Int] = Array(12, 45, 23)
scala> val strArr = new Array[String](3)
strArr: Array[String] = Array(null, null, null)
scala> strArr(0) = "BigData"
scala> strArr(1) = "Hive"
scala> strArr(1) = "HBase"
scala> strArr(2) = "Hive"
scala> for (i <- 0 to 2) println(strArr(i))
BigData
HBase
Hive

scala> val strArr = Array("Hadoop","Hive","Hbase")
strArr: Array[String] = Array(Hadoop, Hive, Hbase)
  • Array提供了函数ofDim来定义二维和三维数组,用法如下:

scala> val myMatrix = Array.ofDim[Int](3,4) //类型实际就是Array[Array[Int]]
myMatrix: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))
scala> val myCube = Array.ofDim[String](3,2,4) //类型实际是Array[Array[Array[String]]]
myCube: Array[Array[Array[String]]] = Array(Array(Array(null, null, null, null), Array(null, null, null, null)), Array(Array(null, null, null, null), Array(null, null, null, null)), Array(Array(null, null, null, null), Array(null, null, null, null)))
  • 可以使用多级圆括号来访问多维数组的元素,例如myMatrix(0)(1)返回第 一行第二列的元素

  • 采用Array类型定义的数组属于定长数组,其数组长度 在初始化后就不能改变。如果要定义变长数组,需要使用ArrayBuffer参数类型,其位于包 scala.collection.mutable中。举例如下:

scala> import scala.collection.mutable.ArrayBuffer 
import scala.collection.mutable.ArrayBuffer
scala> val aMutableArr = ArrayBuffer(10,20,30)
aMutableArr: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 30)
scala> aMutableArr += 40
res37: aMutableArr.type = ArrayBuffer(10, 20, 30, 40)
scala> aMutableArr.insert(2, 60,40)
scala> aMutableArr
res39: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 60, 40, 30, 40)
scala> aMutableArr -= 40
res40: aMutableArr.type = ArrayBuffer(10, 20, 60, 30, 40)
scala> var temp=aMutableArr.remove(2)
temp: Int = 60

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val aMutableArr = ArrayBuffer(10,20,30)
aMutableArr: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 30)
scala> aMutableArr ++= Array(4,5,6)  //追加数组
res11: aMutableArr.type = ArrayBuffer(10, 20, 30, 4, 5, 6
scala> var temp=aMutableArr.remove(2,2) //从第二个元素删除,删除2个元素
temp: Unit = ()
scala> aMutableArr
res12: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 5, 6)

元组(Tuple)

  • 元组是不同类型的值的聚集。元组和列表不同,列表中各 个元素必须是相同类型,而元组可以包含不同类型的元素

scala> val tuple = ("bigdata" , 2015 , 45.0 , 33f)
tuple: (String, Int, Double, Float) = (bigdata,2015,45.0,33.0)
scala> println(tuple._1)
bigdata
scala> println(tuple._2)
2015
scala> println(tuple._4)
33.0
scala> val t,(a,b,c,d) = ("bigdata" , 2015 , 45.0 , 33f)
t: (String, Int, Double, Float) = (bigdata,2015,45.0,33.0)
a: String = bigdata
b: Int = 2015
c: Double = 45.0
d: Float = 33.0
scala> a
res0: String = bigdata

Scala_数据结构的更多相关文章

  1. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  2. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  3. 深入浅出Redis-redis底层数据结构(上)

    1.概述 相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-valu ...

  4. 算法与数据结构(十五) 归并排序(Swift 3.0版)

    上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...

  5. 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)

    本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...

  6. 算法与数据结构(九) 查找表的顺序查找、折半查找、插值查找以及Fibonacci查找

    今天这篇博客就聊聊几种常见的查找算法,当然本篇博客只是涉及了部分查找算法,接下来的几篇博客中都将会介绍关于查找的相关内容.本篇博客主要介绍查找表的顺序查找.折半查找.插值查找以及Fibonacci查找 ...

  7. 算法与数据结构(八) AOV网的关键路径

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...

  8. 算法与数据结构(七) AOV网的拓扑排序

    今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...

  9. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

随机推荐

  1. istream_iterator和ostream_iterator

    总结: istream_iterator<T>in(strm);T指明此istream_iterator的输入类型,strm为istream_iterator指向的流 提供了输入操作符(& ...

  2. elasticsearch权威指南

    elasticsearch权威指南 https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/

  3. BPF+XDP比较全的资料都在这里

    Dive into BPF: a list of reading material Sep 1, 2016 • Quentin Monnet◀Table of contents What is BPF ...

  4. Laravel 利用 observer 类基于状态属性,对进行删除和修改的控制

    1 我们知道 Observer 类可以监听模型类的相关事件 1.1 creating, created, updating, updated, saving, saved, deleting, del ...

  5. PhpStorm 为 Laravel 搭建 PhpUnit 单元测试环境

    1.PhpStorm 中打开项目的路径为 Laravel 安装的根目录 2.点击右下角 EventLog 提示按钮, 初始化 Composer 的设置 3.打开单元单测试示例类,按提示点击 Fix . ...

  6. Netty 源码 NioEventLoop(三)执行流程

    Netty 源码 NioEventLoop(三)执行流程 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 上文提到在启动 N ...

  7. gunicorn配置文件

    最近使用gunicorn部署,感觉用命令参数方式启动比较繁琐,而且有时候就忘了以前怎么设置的了.一笑... 上stackoverflow查了查,找到了一个官方示例,在这里. 官方解释在这里. 记在这里 ...

  8. 在WebGrid中做 批量删除操作

    一般的MVC WebGrid都是在每一行中加入 Edit Detail Delete 这些Link 去对每条记录去单独操作. 稍微研究了一下总结一个 做批量删除的办法. 1. 首先是在WebGrid中 ...

  9. SpringMVC环境搭建和详解

    1.Spring容器和SpringMVC容器是父子容器 1.1 SpringMVC容器可以调用Spring容器中的所有内容 1.2 图示 2.SpringMVC环境搭建 1.导入jar包 2.在web ...

  10. Linux硬件信息命令大全

    硬件信息 在linux系统中,有很多命令可以用于查询主机的硬件信息,有些命令仅仅针对于特定的硬件部件,比如cpu,内存等,而有些命令可以查询很多的硬件信息. 这篇帖子简单地带大家了解一下最常用的查询各 ...