Scala编程——第10章:Scala集合——列表(3)


本节主要学习列表List集合的概念和相关操作。 List是Scala中最重要和最常使用的集合。

一、列表简介

  • 列表是Seq的子类。Seq是一个有先次序的值的序列,具有一定长度的可迭代访问的对象。
  • 列表分成 不可变列表List可变列表ListBuffer
  • List中可以存放任何数据类型, 但是和数组一样,同一个列表的元素必须是相同类型的
  • 继承关系
    • 不可变列表List
      List -> LinearSeq -> Seq -> Iterable -> Traversable
    • 可变列表ListBuffer
      ListBuffer -> Buffer -> Seq -> Iterable -> Traversable
  • 比对Java
    Scala中的List 和Java List 不一样,在Java中List是一个接口,真正存放数据是ArrayList/LinkedList,而Scala的List是一个object,可以直接存放数据。Scala在LinearSeq下面有LinkedList 、DoubleLinkedList 和 MutableList 这三个都不推荐使用,已经过时

二、不可变列表List

默认情况下,Scala提供的List是不可变的,位于scala.collection.immutable.List。在Scala中列表要么是Nil(空表),要么就是head元素加上一个tail,而tail又是一个列表。

1.构建列表

所有的构建本质上都是来自两个基础的构建单元: 空列表"Nil" 和 中缀操作符"::" 。 中缀操作符"::"表示在列表的前面追加元素

  • 常用的创建方式
    val nums: List[Int] = List(1,2,3,4) // nums类型可以省略,会自动推断出来
    val fruit: List[String] = List("apples","oranges","pears")
    val empty: List[Nothing] = List()
    
    底层调用的Object List伴生对象的apply方法。 apply方法的底层也是由 “Nil” + “::” 定义的包装方法。
  • "Nil" + “::” 创建方式
    val nums = 1::(2::(3::(4::Nil)))
    
    由于 “::” 右结合的。 A :: B :: C 底层会自动翻译成 A::(B::C) 所以可以去到圆括号定义,即:
    val nums = 1 :: 2 :: 3 :: 4 :: Nil
    

2.基本操作

对于列表的基本操作有以下三个方法:

  • head: 返回列表的第一个元素
  • tail: 返回列表中除了第一个元素之外的所有所元素(注意:不是返回最后一个元素。)
  • isEmpty: 返回列表是否为空列表
    nums.head
    nums.tail
    nums.isEmpty
    
    在这里插入图片描述

3.初阶方法

如果一个方法不接收任何函数做为入参,就称作初阶(first-order)方法

  • ①拼接列表":::"
    "::"用于拼接元素。":::"用于拼接列表":::"也是右拼接的,在右边列表的前面拼接列表。
    xs ::: ys ::: zs 底层对应 xs ::: (ys ::: zs) 。

    List(1,2) ::: List(3,4,5)
    List(3,4,5) ::: List(1,2) //一定要注意 ::: 的结合顺序  右结合。
    

    在这里插入图片描述

  • ②获取长度:length
    length: 计算链表的长度

    List(1,2,3).length
    

    在这里插入图片描述
    相比数组,列表在length操作上更耗资源。需要遍历整个列表,直到列表尾部。所以当需要判断列表是否为空的操作建议使用 xs.isEmpty 替换 xs.length == 0

  • ③访问列表末端:init 和 last
    last: 返回非空列表的最后一个元素。 对应 head
    init: 返回非空列表除了最后一个元素意外的元素。 对应 tail
    在这里插入图片描述
    init和last也需要遍历整个列表,时间复杂为O(n) n为列表元素个数。

  • ④反转列表:reverse
    如果需要频繁的访问列表的尾部,可以考虑先将列表反转。reverse会创建一个新的列表,不会对原列表做修改。
    在这里插入图片描述

  • ⑤前缀和后缀:take、drop、splitAt
    take: 返回列表的前n个元素
    drop: 返回列表除了前n个元素以外的元素
    splitAt:指定列表下标位置切分,返回切分后的两个列表
    在这里插入图片描述

  • ⑥元素选择:apply 、indices、iterator
    apply方法:apply方法支持从任意位置选取元素,不对相对数组,列表很少使用在这里插入图片描述
    indices方法:返回包含列表所有有效的下标列表

    在这里插入图片描述
    iterator:通过迭代器访问列表元素

    在这里插入图片描述

  • ⑦扁平化列表:flatten
    flatten方法:接收一个列表的列表,并将它扁平化,返回单个列表。
    在这里插入图片描述

  • ⑧列表拉链:zip 和 unzip
    zip:接收两个列表,返回一个由对偶组成的列表。如果列表的长度不同,将丢失没有配对的元素。
    在这里插入图片描述
    zipWithIndex:将列表元素和对应下标组合成对偶列表
    在这里插入图片描述
    unzip:将对偶列表 转换回由列表组成的元组
    在这里插入图片描述

  • ⑨显示列表:toString 和 mkString
    toString:返回列表的标准字符串表现形式
    mkString:返回列表指定形式的字符串表现形式。mkString(pre,sep,post):pre:最前面的字符,sep:元素之间的分隔字符串, post:最后面的字符串
    在这里插入图片描述

  • ⑩列表转换: iterator、toArray、copyToArray
    toArray: 将列表转换成数组
    在这里插入图片描述

    copyToArray: 将列表中的元素依次复制到目标数组的指定位置。copyToArray(arr,start): arr目标数组,start复制的起始索引位置
    在这里插入图片描述

4.高阶方法

许多对列表的操作都有相似的结构,有一些模式反复的出现。例如对列表的元素做转换等等。在Java中通常需要通过固定写法的for循环或者while循环来实现。而Scala允许我们使用高阶方法来更加精简、直接地表达。

  • ①列表映射: map 、 flatMap 、 foreach

    xs map f : 将类型为List[T]的列表xs 和 类型为 T=>U的函数f 作为操作元。返 函数f应用到 xs每个元素后的列表。在这里插入图片描述

    这种写法避免了繁杂的for循环或者while循环。

    xs flatMap f : 与map类似,flatma会有个扁平化的操作。下面清楚的显示了两者的区别:map返回的是列表的列表,flatMap返回的是所有元素拼接起来的单个列表。
    在这里插入图片描述
    xs foreach f: foreach 要求右操作元f 是一个过程(结果类型是Unit的函数),它是简单将过程f应用到每个元素。整个操作本身的结果类型也是Unit,并没有列表的类型结果被组装出来。例如列表求和:
    在这里插入图片描述

  • ②列表过滤:filter、partition、find 、takeWhile、dropWhile、span

    xs filter p: 两个操作元分别是:类型为List[T]的xs列表 和 类型为 T=> Boolean的条件函数p。返回xs列表中 所有p(x)为true的元素x列表。
    在这里插入图片描述
    xs patition p :和filter类似,不过返回两个列表,其中一个是p(x)为true的元素列表,另一个是p(x)为false的元素列表。
    即 xs patition p = (xs filter p , xs filter !p)
    在这里插入图片描述
    xs find p: 返回满足条件的第一个元素,而不是所有元素。返回值是一个可选值Option类型。
    在这里插入图片描述
    xs takeWhile p :返回列表中满足p的最长连续元素的列表(从第一个元素开始判断,不满足就是空)
    在这里插入图片描述

    xs dropWhile p: 返回列表中不满足p的最长连续元素的列表
    在这里插入图片描述
    xs span p: 将takeWhile和dropWhile操作合二为一。 等价于 (xs takeWhile p, xs dropWhile p)
    在这里插入图片描述

  • ③ 列表前置条件检查: forall 、exists
    xs forall p : 如果xs列表的所有元素都满足p 就返回true。
    xs exists p: 如果xs列表存在至少一个元素满足p 就返回true
    在这里插入图片描述

  • ④ 列表折叠: 左折叠 /: 和右折叠 :\

    • 左折叠 " (z /: xs)(op)" 涉及三个对象: 起始值z、列表xs、二元操作函数op 。折叠的结果是以z为前缀,对列表的元素依次连续应用op。
      在这里插入图片描述
      示例:拼接字符串
      wo'r
      这样拼接出来的字符串前面会有一个空格,因为初始值给的是" ",可以这样解决
      在这里插入图片描述
    • 右折叠:"(xs :\ z)(op)" 三个操作元和左折叠类似。折叠的结果是以z为后缀,对列表的元素倒序依次连续应用op。
      在这里插入图片描述
      示例:拼接字符串
      在这里插入图片描述
    • 使用左右折叠的方法名:foldLeft 和 foldRight
      折叠操作符可能记不清楚,可以使用对应的方法名
      在这里插入图片描述
  • ⑤列表排序:sortWith
    xs sortWith before: 对列表xs中的元素进行排序。 before 是比较两个元素的函数。表达式 x before y 对于在预期排序中 x 应该出来在y之前的情况应该返回true。
    在这里插入图片描述

5.List 对象的方法

到目前为止,介绍的所有操作都是 List 类的方法,因此我们其实是在每个具体的列表对象上调用方法。还有一些方法是定义在全局可访问对象scala.list 上的,这是 List 类的伴生对象 。某些操作是用于创建列表的工厂方法,另一些是对特定形状的列表进行操。这两类方法在本节都会介绍。

  • ①从元素创建列表: List.apply
    List(l, 2, 3)这样的字面量只不过是简单地将对象LIst 应用到元素1,2,3而已。也就是说,它跟 List.apply(1,2,3)是等效的:
    在这里插入图片描述
  • ②创建数值区间:List.range
    List.range: 它创建一个包含一个区间的数值的列表。
    List.rang( from,until): 创建一个包含了从 from 开始递增到 **until-1的列表。**不含有until List.rang(from,until,step): 创建一个包含了从 from 开始,递增间隔为 step ,到 until-1的列表
    在这里插入图片描述
  • ③创建相同元素的列表:List.fill
    fill : 创建包含零个或多个同一个元素拷贝的列表。它接收两个参数:要创建的列表长度和需要重复的元素。两个参数各自以不同的参数列表给出。
    在这里插入图片描述
    如果我们给fill的参数多于1个,那么它就会创建多维的列表。
    在这里插入图片描述
  • ④拼接多个列表:List.concat
    concat: 将多个列表拼接在一起。要拼接的列表通过 concat 的直接入参给出。
    在这里插入图片描述

三、可变列表

ListBuffer是可变的list集合,可以添加,删除元素,ListBuffer属于序列。
List 类提供对列表头部的快速访问,对尾部访问则没那么高效。当需要往列表尾部追加元素来构建列表时,通常要考虑反过来往头部追加元素,追加完成以后,再调用 reverse 来获得想要的顺序。

另一种避免 reverse 操作的可选方案是使用 ListBuffer。ListBuffer 提供了常量时间的往后追加和往前追加的操作。可以调用 ListBuffer的toList 来获取最终的List。

1.常用方法

  • ①创建ListBuffer:使用可变列表需要先导入包 scala.collection.mutable.ListBuffer
    在这里插入图片描述
  • ②追加元素:+= 向后追加 +=:向前追加
    在这里插入图片描述
  • ③ 转为不可变列表: toList
    在这里插入图片描述
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页