一、List字面量

List是Scala中非常重要的一个数据结构,其与Array(数组)非常类似,但是List是不可变的,和Java中的List一样,其底层实现是链表。

  1. scala> val list = List("hadoop", "spark", "storm")
  2. list: List[String] = List(hadoop, spark, storm)
  3. // List是不可变
  4. scala> list(1) = "hive"
  5. <console>:9: error: value update is not a member of List[String]

二、List类型

Scala中List具有以下两个特性:

  • 同构(homogeneous):同一个List中的所有元素都必须是相同的类型;
  • 协变(covariant):如果S是T的子类型,那么List[S]就是List[T]的子类型,例如List[String]List[Object]的子类型。

需要特别说明的是空列表的类型为List[Nothing]

  1. scala> List()
  2. res1: List[Nothing] = List()

三、构建List

所有List都由两个基本单元构成:Nil::(读作"cons")。即列表要么是空列表(Nil),要么是由一个head加上一个tail组成,而tail又是一个List。我们在上面使用的List("hadoop", "spark", "storm")最终也是被解释为"hadoop"::"spark":: "storm"::Nil

  1. scala> val list01 = "hadoop"::"spark":: "storm"::Nil
  2. list01: List[String] = List(hadoop, spark, storm)
  3. // :: 操作符号是右结合的,所以上面的表达式和下面的等同
  4. scala> val list02 = "hadoop"::("spark":: ("storm"::Nil))
  5. list02: List[String] = List(hadoop, spark, storm)

四、模式匹配

Scala支持展开列表以实现模式匹配。

  1. scala> val list = List("hadoop", "spark", "storm")
  2. list: List[String] = List(hadoop, spark, storm)
  3. scala> val List(a,b,c)=list
  4. a: String = hadoop
  5. b: String = spark
  6. c: String = storm

如果只需要匹配部分内容,可以如下:

  1. scala> val a::rest=list
  2. a: String = hadoop
  3. rest: List[String] = List(spark, storm)

五、列表的基本操作

5.1 常用方法

  1. object ScalaApp extends App {
  2. val list = List("hadoop", "spark", "storm")
  3. // 1.列表是否为空
  4. list.isEmpty
  5. // 2.返回列表中的第一个元素
  6. list.head
  7. // 3.返回列表中除第一个元素外的所有元素 这里输出List(spark, storm)
  8. list.tail
  9. // 4.tail和head可以结合使用
  10. list.tail.head
  11. // 5.返回列表中的最后一个元素 与head相反
  12. list.init
  13. // 6.返回列表中除了最后一个元素之外的其他元素 与tail相反 这里输出List(hadoop, spark)
  14. list.last
  15. // 7.使用下标访问元素
  16. list(2)
  17. // 8.获取列表长度
  18. list.length
  19. // 9. 反转列表
  20. list.reverse
  21. }

5.2 indices

indices方法返回所有下标。

  1. scala> list.indices
  2. res2: scala.collection.immutable.Range = Range(0, 1, 2)

5.3 take & drop & splitAt

  • take:获取前n个元素;
  • drop:删除前n个元素;
  • splitAt:从第几个位置开始拆分。
  1. scala> list take 2
  2. res3: List[String] = List(hadoop, spark)
  3. scala> list drop 2
  4. res4: List[String] = List(storm)
  5. scala> list splitAt 2
  6. res5: (List[String], List[String]) = (List(hadoop, spark),List(storm))

5.4 flatten

flatten接收一个由列表组成的列表,并将其进行扁平化操作,返回单个列表。

  1. scala> List(List(1, 2), List(3), List(), List(4, 5)).flatten
  2. res6: List[Int] = List(1, 2, 3, 4, 5)

5.5 zip & unzip

对两个List执行zip操作结果如下,返回对应位置元素组成的元组的列表,unzip则执行反向操作。

  1. scala> val list = List("hadoop", "spark", "storm")
  2. scala> val score = List(10,20,30)
  3. scala> val zipped=list zip score
  4. zipped: List[(String, Int)] = List((hadoop,10), (spark,20), (storm,30))
  5. scala> zipped.unzip
  6. res7: (List[String], List[Int]) = (List(hadoop, spark, storm),List(10, 20, 30))

5.6 toString & mkString

toString 返回List的字符串表现形式。

  1. scala> list.toString
  2. res8: String = List(hadoop, spark, storm)

如果想改变List的字符串表现形式,可以使用mkString。mkString有三个重载方法,方法定义如下:

  1. // start:前缀 sep:分隔符 end:后缀
  2. def mkString(start: String, sep: String, end: String): String =
  3. addString(new StringBuilder(), start, sep, end).toString
  4. // seq 分隔符
  5. def mkString(sep: String): String = mkString("", sep, "")
  6. // 如果不指定分隔符 默认使用""分隔
  7. def mkString: String = mkString("")

使用示例如下:

  1. scala> list.mkString
  2. res9: String = hadoopsparkstorm
  3. scala> list.mkString(",")
  4. res10: String = hadoop,spark,storm
  5. scala> list.mkString("{",",","}")
  6. res11: String = {hadoop,spark,storm}

5.7 iterator & toArray & copyToArray

iterator 方法返回的是迭代器,这和其他语言的使用是一样的。

  1. object ScalaApp extends App {
  2. val list = List("hadoop", "spark", "storm")
  3. val iterator: Iterator[String] = list.iterator
  4. while (iterator.hasNext) {
  5. println(iterator.next)
  6. }
  7. }

toArray和toList用于List和数组之间的互相转换。

  1. scala> val array = list.toArray
  2. array: Array[String] = Array(hadoop, spark, storm)
  3. scala> array.toList
  4. res13: List[String] = List(hadoop, spark, storm)

copyToArray将List中的元素拷贝到数组中指定位置。

  1. object ScalaApp extends App {
  2. val list = List("hadoop", "spark", "storm")
  3. val array = Array("10", "20", "30")
  4. list.copyToArray(array,1)
  5. println(array.toBuffer)
  6. }
  7. // 输出 :ArrayBuffer(10, hadoop, spark)

六、列表的高级操作

6.1 列表转换:map & flatMap & foreach

map 与 Java 8 函数式编程中的map类似,都是对List中每一个元素执行指定操作。

  1. scala> List(1,2,3).map(_+10)
  2. res15: List[Int] = List(11, 12, 13)

flatMap 与 map 类似,但如果List中的元素还是List,则会对其进行flatten操作。

  1. scala> list.map(_.toList)
  2. res16: List[List[Char]] = List(List(h, a, d, o, o, p), List(s, p, a, r, k), List(s, t, o, r, m))
  3. scala> list.flatMap(_.toList)
  4. res17: List[Char] = List(h, a, d, o, o, p, s, p, a, r, k, s, t, o, r, m)

foreach 要求右侧的操作是一个返回值为Unit的函数,你也可以简单理解为执行一段没有返回值代码。

  1. scala> var sum = 0
  2. sum: Int = 0
  3. scala> List(1, 2, 3, 4, 5) foreach (sum += _)
  4. scala> sum
  5. res19: Int = 15

6.2 列表过滤:filter & partition & find & takeWhile & dropWhile & span

filter用于筛选满足条件元素,返回新的List。

  1. scala> List(1, 2, 3, 4, 5) filter (_ % 2 == 0)
  2. res20: List[Int] = List(2, 4)

partition会按照筛选条件对元素进行分组,返回类型是tuple(元组)。

  1. scala> List(1, 2, 3, 4, 5) partition (_ % 2 == 0)
  2. res21: (List[Int], List[Int]) = (List(2, 4),List(1, 3, 5))

find查找第一个满足条件的值,由于可能并不存在这样的值,所以返回类型是Option,可以通过getOrElse在不存在满足条件值的情况下返回默认值。

  1. scala> List(1, 2, 3, 4, 5) find (_ % 2 == 0)
  2. res22: Option[Int] = Some(2)
  3. val result: Option[Int] = List(1, 2, 3, 4, 5) find (_ % 2 == 0)
  4. result.getOrElse(10)

takeWhile遍历元素,直到遇到第一个不符合条件的值则结束遍历,返回所有遍历到的值。

  1. scala> List(1, 2, 3, -4, 5) takeWhile (_ > 0)
  2. res23: List[Int] = List(1, 2, 3)

dropWhile遍历元素,直到遇到第一个不符合条件的值则结束遍历,返回所有未遍历到的值。

  1. // 第一个值就不满足条件,所以返回列表中所有的值
  2. scala> List(1, 2, 3, -4, 5) dropWhile (_ < 0)
  3. res24: List[Int] = List(1, 2, 3, -4, 5)
  4. scala> List(1, 2, 3, -4, 5) dropWhile (_ < 3)
  5. res26: List[Int] = List(3, -4, 5)

span遍历元素,直到遇到第一个不符合条件的值则结束遍历,将遍历到的值和未遍历到的值分别放入两个List中返回,返回类型是tuple(元组)。

  1. scala> List(1, 2, 3, -4, 5) span (_ > 0)
  2. res27: (List[Int], List[Int]) = (List(1, 2, 3),List(-4, 5))

6.3 列表检查:forall & exists

forall检查List中所有元素,如果所有元素都满足条件,则返回true。

  1. scala> List(1, 2, 3, -4, 5) forall ( _ > 0 )
  2. res28: Boolean = false

exists检查List中的元素,如果某个元素已经满足条件,则返回true。

  1. scala> List(1, 2, 3, -4, 5) exists (_ > 0 )
  2. res29: Boolean = true

6.4 列表排序:sortWith

sortWith对List中所有元素按照指定规则进行排序,由于List是不可变的,所以排序返回一个新的List。

  1. scala> List(1, -3, 4, 2, 6) sortWith (_ < _)
  2. res30: List[Int] = List(-3, 1, 2, 4, 6)
  3. scala> val list = List( "hive","spark","azkaban","hadoop")
  4. list: List[String] = List(hive, spark, azkaban, hadoop)
  5. scala> list.sortWith(_.length>_.length)
  6. res33: List[String] = List(azkaban, hadoop, spark, hive)

七、List对象的方法

上面介绍的所有方法都是List类上的方法,下面介绍的是List伴生对象中的方法。

7.1 List.range

List.range可以产生指定的前闭后开区间内的值组成的List,它有三个可选参数: start(开始值),end(结束值,不包含),step(步长)。

  1. scala> List.range(1, 5)
  2. res34: List[Int] = List(1, 2, 3, 4)
  3. scala> List.range(1, 9, 2)
  4. res35: List[Int] = List(1, 3, 5, 7)
  5. scala> List.range(9, 1, -3)
  6. res36: List[Int] = List(9, 6, 3)

7.2 List.fill

List.fill使用指定值填充List。

  1. scala> List.fill(3)("hello")
  2. res37: List[String] = List(hello, hello, hello)
  3. scala> List.fill(2,3)("world")
  4. res38: List[List[String]] = List(List(world, world, world), List(world, world, world))

7.3 List.concat

List.concat用于拼接多个List。

  1. scala> List.concat(List('a', 'b'), List('c'))
  2. res39: List[Char] = List(a, b, c)
  3. scala> List.concat(List(), List('b'), List('c'))
  4. res40: List[Char] = List(b, c)
  5. scala> List.concat()
  6. res41: List[Nothing] = List()

八、处理多个List

当多个List被放入同一个tuple中时候,可以通过zipped对多个List进行关联处理。

  1. // 两个List对应位置的元素相乘
  2. scala> (List(10, 20), List(3, 4, 5)).zipped.map(_ * _)
  3. res42: List[Int] = List(30, 80)
  4. // 三个List的操作也是一样的
  5. scala> (List(10, 20), List(3, 4, 5), List(100, 200)).zipped.map(_ * _ + _)
  6. res43: List[Int] = List(130, 280)
  7. // 判断第一个List中元素的长度与第二个List中元素的值是否相等
  8. scala> (List("abc", "de"), List(3, 2)).zipped.forall(_.length == _)
  9. res44: Boolean = true

九、缓冲列表ListBuffer

上面介绍的List,由于其底层实现是链表,这意味着能快速访问List头部元素,但对尾部元素的访问则比较低效,这时候可以采用ListBuffer,ListBuffer提供了在常量时间内往头部和尾部追加元素。

  1. import scala.collection.mutable.ListBuffer
  2. object ScalaApp extends App {
  3. val buffer = new ListBuffer[Int]
  4. // 1.在尾部追加元素
  5. buffer += 1
  6. buffer += 2
  7. // 2.在头部追加元素
  8. 3 +=: buffer
  9. // 3. ListBuffer转List
  10. val list: List[Int] = buffer.toList
  11. println(list)
  12. }
  13. //输出:List(3, 1, 2)

十、集(Set)

Set是不重复元素的集合。分为可变Set和不可变Set。

10.1 可变Set

  1. object ScalaApp extends App {
  2. // 可变Set
  3. val mutableSet = new collection.mutable.HashSet[Int]
  4. // 1.添加元素
  5. mutableSet.add(1)
  6. mutableSet.add(2)
  7. mutableSet.add(3)
  8. mutableSet.add(3)
  9. mutableSet.add(4)
  10. // 2.移除元素
  11. mutableSet.remove(2)
  12. // 3.调用mkString方法 输出1,3,4
  13. println(mutableSet.mkString(","))
  14. // 4. 获取Set中最小元素
  15. println(mutableSet.min)
  16. // 5. 获取Set中最大元素
  17. println(mutableSet.max)
  18. }

10.2 不可变Set

不可变Set没有add方法,可以使用+添加元素,但是此时会返回一个新的不可变Set,原来的Set不变。

  1. object ScalaApp extends App {
  2. // 不可变Set
  3. val immutableSet = new collection.immutable.HashSet[Int]
  4. val ints: HashSet[Int] = immutableSet+1
  5. println(ints)
  6. }
  7. // 输出 Set(1)

10.3 Set间操作

多个Set之间可以进行求交集或者合集等操作。

  1. object ScalaApp extends App {
  2. // 声明有序Set
  3. val mutableSet = collection.mutable.SortedSet(1, 2, 3, 4, 5)
  4. val immutableSet = collection.immutable.SortedSet(3, 4, 5, 6, 7)
  5. // 两个Set的合集 输出:TreeSet(1, 2, 3, 4, 5, 6, 7)
  6. println(mutableSet ++ immutableSet)
  7. // 两个Set的交集 输出:TreeSet(3, 4, 5)
  8. println(mutableSet intersect immutableSet)
  9. }

参考资料

  1. Martin Odersky . Scala编程(第3版)[M] . 电子工业出版社 . 2018-1-1
  2. 凯.S.霍斯特曼 . 快学Scala(第2版)[M] . 电子工业出版社 . 2017-7

更多大数据系列文章可以参见个人 GitHub 开源项目: 程序员大数据入门指南

Scala 学习之路(六)—— 常用集合类型之 List & Set的更多相关文章

  1. Java学习之路(六):集合

    集合的由来 数组的长度是固定的,当添加的元素超过了数组的长度,就需要对数组重新定义 java内部给我们提供的集合类,能存储任意对象,长度是可以改变的.随着元素的增加而增加,随着元素的减少而减少 数组和 ...

  2. Scala 系列(七)—— 常用集合类型之 Map & Tuple

    一.映射(Map) 1.1 构造Map // 初始化一个空 map val scores01 = new HashMap[String, Int] // 从指定的值初始化 Map(方式一) val s ...

  3. Scala 学习之路(五)—— 集合类型综述

    一.集合简介 Scala中拥有多种集合类型,主要分为可变的和不可变的集合两大类: 可变集合: 可以被修改.即可以更改,添加,删除集合中的元素: 不可变集合类:不能被修改.对集合执行更改,添加或删除操作 ...

  4. Scala学习之路 (六)Scala的类、对象、继承、特质

    一.类 1.类的定义 scala语言中没有static成员存在,但是scala允许以某种方式去使用static成员这个就是伴生机制,所谓伴生,就是在语言层面上,把static成员和非static成员用 ...

  5. Scala学习之路 (四)Scala的数组、映射、元组、集合

    一.数组 1.定长数组和变长数组 import scala.collection.mutable.ArrayBuffer object TestScala { def main(args: Array ...

  6. Scala学习之路 (三)Scala的基本使用

    一.Scala概述 scala是一门多范式编程语言,集成了面向对象编程和函数式编程等多种特性.scala运行在虚拟机上,并兼容现有的Java程序.Scala源代码被编译成java字节码,所以运行在JV ...

  7. Scala 学习之路(三)—— 流程控制语句

    一.条件表达式if Scala中的if/else语法结构与Java中的一样,唯一不同的是,Scala中的if表达式是有返回值的. object ScalaApp extends App { val x ...

  8. Guava学习笔记:Guava新增集合类型-Bimap

    BiMap提供了一种新的集合类型,它提供了key和value的双向关联的数据结构. 通常情况下,我们在使用Java的Map时,往往是通过key来查找value的,但是如果出现下面一种场景的情况,我们就 ...

  9. Guava学习笔记:Guava新增集合类型-Multimap

    在日常的开发工作中,我们有的时候需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比较复杂的集合类型的数据结构,以便做相应的业 ...

  10. Guava学习笔记:Guava新增集合类型-Multiset

    Guava引进了JDK里没有的,但是非常有用的一些新的集合类型.所有这些新集合类型都能和JDK里的集合平滑集成.Guava集合非常精准地实现了JDK定义的接口.Guava中定义的新集合有: Multi ...

随机推荐

  1. 从源码角度看MySQL memcached plugin——0.大纲

    本系列文章介绍MySQL memcached plugin插件.剖析已经完成.先把链接弄好,内容会陆续补上. 大纲如下: 系统结构和引擎初始化(已完成) 线程模型和连接的状态机 containers表 ...

  2. CefSharp For WPF自定义右键菜单栏

    原文:CefSharp For WPF自定义右键菜单栏 初始化 <!--浏览器--> <cefSharpWPF:ChromiumWebBrowser Name="webBr ...

  3. 许多其他C++的class样本

    class A{  public:  A(){}//构造函数,作用分配类所需的空间 }; int main() {  A a; } a它是类A示例! 版权声明:本文博客原创文章.博客,未经同意,不得转 ...

  4. UVA - 825Walking on the Safe Side(dp)

    id=19217">称号: UVA - 825Walking on the Safe Side(dp) 题目大意:给出一个n * m的矩阵.起点是1 * 1,终点是n * m.这个矩阵 ...

  5. jquery评分星星

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  6. WPF 数据模板DataType属性的使用,不用指定ItemTemplate

    <Window x:Class="CollectionBinding.MainWindow"        xmlns="http://schemas.micros ...

  7. gnuradio companion 找不到第三方模块gr-osmosdr的问题

    我使用了来自Ettus的gnuradio软件包,之后安装了gr-osmosdr 以在gnuradio中调用RTL电视棒. 但是在gnuradio companion找不到来自rtlsdr-source ...

  8. RestSharp 封状实例

    1 public class Rest<T> { private static Logger logger = LogManager.GetCurrentClassLogger(); pr ...

  9. Android 查看Apk签名方式V1和V2

    Android 查看Apk签名方式V1和V2 java -jar apksigner.jar verify -v my.apk -- Verifies Verified using v1 scheme ...

  10. Win8 Metro(C#)数字图像处理--2.45图像雾化效果算法

    原文:Win8 Metro(C#)数字图像处理--2.45图像雾化效果算法 [函数名称]   图像雾化         AtomizationProcess(WriteableBitmap src,i ...