内容简介:Seq 是一个特质类型(定义如下),用于表示按照一定顺序排列的元素序列,Seq 继承了偏函数 PartialFunction 特质,所以一个序列本质上也是一个偏函数,对应的函数类型是Seq 同样分为可变和不可变两大类,此外还派生出 IndexedSeq 和 LinearSeq 两个重要的子特质:IndexedSeq 特质典型的实现类有 ArraySeq、Vector,以及 Range 等,其中 Vector 基于 Trie 树实现,在随机读和随机更新方面进行了权衡,虽然随机读的时间相对于数组略长,但是随机更
Seq 是一个特质类型(定义如下),用于表示按照一定顺序排列的元素序列,Seq 继承了偏函数 PartialFunction 特质,所以一个序列本质上也是一个偏函数,对应的函数类型是 Int => A
,其中 A 是对应 Seq 的元素类型,而输入参数是 Seq 的下标。
trait Seq[+A] extends PartialFunction[Int, A] with Iterable[A] with GenSeq[A] with GenericTraversableTemplate[A, Seq] with SeqLike[A, Seq[A]]
Seq 同样分为可变和不可变两大类,此外还派生出 IndexedSeq 和 LinearSeq 两个重要的子特质:
- IndexedSeq :代表索引序列,对于基于索引的操作来说效率较高,一般底层依赖于数组实现。
- LinearSeq :代表线性序列,对于 head、tail,以及 isEmpty 一类的方法效率较高,一般底层依赖于链表实现。
IndexedSeq 特质典型的实现类有 ArraySeq、Vector,以及 Range 等,其中 Vector 基于 Trie 树实现,在随机读和随机更新方面进行了权衡,虽然随机读的时间相对于数组略长,但是随机更新性能要优于数组和链表,是 iimmutable IndexedSeq 的默认实现。
LinearSeq 特质的典型实现类就是 List 类型,不过 List 是一个抽象类,默认基于 ListBuffer 构建。ListBuffer 的父特质 Buffer 也是 Seq 派生的一个重要子特质,Buffer 特质声明为 mutable,用于定义可变的 Seq 集合,除了 ListBuffer 实现类,Scala 主要还提供了基于数组的 ArrayBuffer 实现。
一. 获取集合索引
1.1 indexOf & lastIndexOf
函数 indexOf 和 lastIndexOf 均用于从给定 Seq 对象中检索指定元素的下标值(如果不存在则返回 -1),区别在于 indexOf 从左至右开始检索,而 lastIndexOf 则从右至左开始检索,同时这两个方法均允许指定检索的起始下标。函数定义如下:
def indexOf[B >: A](elem: B): Int def indexOf[B >: A](elem: B, from: Int): Int def lastIndexOf[B >: A](elem: B): Int def lastIndexOf[B >: A](elem: B, end: Int): Int
示例:
val seq = Seq('a' to 'z': _*) seq.indexOf('c') // 输出:2 seq.lastIndexOf('h') // 输出:7
1.2 indexWhere & lastIndexWhere
函数 indexWhere 和 lastIndexWhere 相对于 indexOf 和 lastIndexOf 更加灵活一些,这两个函数均允许指定谓词 A => Boolean
来对集合中的元素进行筛选,并返回满足条件的第 1 个元素对应的下标。函数定义如下:
def indexWhere(p: A => Boolean, from: Int): Int def indexWhere(p: A => Boolean): Int def lastIndexWhere(p: A => Boolean): Int def lastIndexWhere(p: A => Boolean, end: Int): Int
示例:
val seq = Seq(1 to 9: _*) seq.indexWhere(x => x % 2 == 0 && x > 5) // 输出:5 seq.lastIndexWhere(x => x % 2 == 1 && x < 5) // 输出:2
实际上 indexOf 和 lastIndexOf 底层分别使用 indexWhere 和 lastIndexWhere 进行实现。
1.3 indexOfSlice & lastIndexOfSlice
函数 indexOfSlice 和 lastIndexOfSlice 用于检索给定的子序列在 Seq 对象中的位置,并返回子序列第 1 个元素对应的下标,如果不存在则返回 -1。函数定义如下:
def indexOfSlice[B >: A](that: GenSeq[B]): Int def indexOfSlice[B >: A](that: GenSeq[B], from: Int): Int def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int
示例:
val seq = Seq(1 to 9: _*) seq.indexOfSlice(Seq(7, 8)) // 输出:6 seq.lastIndexOfSlice(Seq(7, 8)) // 输出:6 seq.indexOfSlice(Seq(1, 8)) // 输出:-1 seq.lastIndexOfSlice(Seq(1, 8)) // 输出:-1
1.4 indices
函数 indices 用于获取 Seq 对象的索引集合,返回一个 Range 对象,示例:
val seq = Seq("A", "B", "C") seq.indices // 输出:Range 0 until 3
二. 获取集合长度
2.1 length & size
函数 length 和 size 都可以返回当前 Seq 对象的长度,区别在于 size 是 Traversable 中定义的方法,而 length 是 Seq 中定义的方法,二者在功能上是等价的。示例:
val seq = Seq(1 to 9: _*) seq.size // 输出:9 seq.length // 输出:9
2.2 lengthCompare
函数 lengthCompare 接收一个参数 n,用于将当前 Seq 对象的长度 l 与该参数进行比较,如果 l > n
则返回 1,如果 l == n
则返回 0,如果 l < n
则返回 l - n
。示例:
val seq = Seq(1 to 9: _*) seq.lengthCompare(8) // 输出:1 seq.lengthCompare(9) // 输出:0 seq.lengthCompare(18) // 输出:-1
为什么 seq.lengthCompare(18)
的结果是 -1,而不是 -9 呢,这是因为这里实际使用的实现类 List 覆盖实现了该方法,强制返回 -1。
2.3 segmentLength & prefixLength
函数 segmentLength 接收一个谓词 A => Boolean
,用于从指定下标 from 开始往右检索连续满足条件的子序列的最大长度,函数定义如下:
def segmentLength(p: A => Boolean, from: Int): Int
而函数 prefixLength 是 segmentLength 的特殊版本,其 from 参数设置为 0,表示从头开始检索,即检索集合满足给定条件的最长前缀子序列,并返回其长度。示例:
val seq = Seq(1 to 9: _*) seq.segmentLength(_ < 5, 2) // 输出:2 seq.prefixLength(_ < 5) // 输出:4
三. 查询操作
3.1 apply
函数 apply 用于从 Seq 对象中获取指定下标的元素,例如 seq.apply(2)
用于获取下标为 2 的元素,也可以简写为 seq(2)
,示例:
val seq = Seq("A", "B", "C") seq.apply(2) // 输出:C seq(2) // 输出:C
四. 插入操作
4.1 +:
& :+
函数 +:
和 :+
均用于往 Seq 对象中追加元素,并返回一个新的集合对象,区别在于 +:
是前置追加,而 :+
是后置追加,示例:
val seq = Seq(2, 3, 4) 1 +: seq // 输出:List(1, 2, 3, 4) seq :+ 5 // 输出:List(2, 3, 4, 5)
4.2 padTo
函数 padTo 用于将当前 Seq 对象中的前 len 个元素复制到新集合中,并在集合元素不够时使用给定的 elem 默认值填充。函数定义如下:
def padTo[B >: A, That](len: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That
示例:
val seq = Seq(2, 3, 4) seq.padTo(5, 0) // 输出:List(2, 3, 4, 0, 0) seq.padTo(2, 0) // 输出:List(2, 3, 4)
五. 更新操作
5.1 updated
函数 updated 用于更新 Seq 对象中指定下标位置的元素值,对于不可变集合的修改会创建出一个新的集合,而对于可变集合来说则是原地修改,所以对于可变集合可以简写为 ()
操作符。示例:
val seq = Seq(1, 2, 3) seq.updated(2, 8) // 输出:List(1, 2, 8) val mseq = mutable.Seq(1, 2, 3) mseq(2) = 8 mseq // 输出:ArrayBuffer(1, 2, 8)
5.2 patch
函数 patch 使用给定的元素序列 patch 替换 Seq 对象中 [from, from + replaced)
下标的元素。函数定义如下:
def patch[B >: A, That](from: Int, patch: GenSeq[B], replaced: Int)(implicit bf: CanBuildFrom[Repr, B, That]): That
示例:
val seq = Seq(1 to 9: _*) seq.patch(3, Seq(8, 8, 8, 8, 8), 2) // 输出:List(1, 2, 3, 8, 8, 8, 8, 8, 6, 7, 8, 9)
六. 排序操作
6.1 sorted & sortBy & sortWith
函数 sorted、sortBy 和 sortWith 均用于对 Seq 对象中的元素进行 排序 操作,区别在于:
- sorted :按照元素的值从小到大进行排序。
- sortBy :按照指定的因子从小到大对集合中的元素进行排序。
-
sortWith
:接收一个比较函数
(A, A) => Boolean
,已该函数对集合中的元素进行排序。
示例:
val seq = Seq.fill(10)(Random.nextInt(100)) seq.sorted // 输出:List(28, 36, 42, 43, 63, 66, 69, 84, 85, 88) seq.sortBy(_ % 10) // 输出:List(42, 63, 43, 84, 85, 66, 36, 88, 28, 69) seq.sortWith((x, y) => y < x) // 输出:List(88, 85, 84, 69, 66, 63, 43, 42, 36, 28)
七. 反转操作
7.1 reverse & reverseIterator & reverseMap
函数 reverse 用于对 Seq 对象中的元素执行反转操作,而函数 reverseIterator 同样执行反转操作,只是返回的是一个迭代器对象,示例:
val seq = Seq(1 to 5: _*) seq.reverse // 输出:List(5, 4, 3, 2, 1) seq.reverseIterator // 输出:<iterator>
函数 reverseMap 相当于 reverse 和 map 的组合,不过执行效率更高,用于对反转的集合执行 map 操作,示例:
val seq = Seq(1 to 5: _*) seq.reverseMap(_ - 5) // 输出:List(0, -1, -2, -3, -4)
八. 包含检查
8.1 contains & containsSlice
函数 contains 用于检查 Seq 对象是否包含指定单个元素,而函数 containsSlice 用于检查是否包含给定的元素序列,示例:
val seq = Seq(1 to 5: _*) seq.contains(3) // 输出:true seq.containsSlice(Seq(1, 2)) // 输出:true seq.containsSlice(Seq(2, 1)) // 输出:false
九. 转换操作
9.1 transform
对于集合来说一般使用 map 函数执行转换操作,但是对于 可变 Seq 对象来说,Scala 还提供了 transform 函数,用于原地转换,示例:
val seq = mutable.Seq(1, 2, 3) seq.transform(_ * 10) seq // 输出:ArrayBuffer(10, 20, 30)
十. 集合运算
10.1 intersect
函数 intersect 用于求解两个集合的 交集 ,示例:
val seq1 = Seq(1, 2, 3, 3) val seq2 = Seq(2, 3, 4, 5) seq1.intersect(seq2) // 输出:List(2, 3)
注意:如果两个集合包含重复元素,假设该元素在集合 A 中出现 x 次,在集合 B 中出现 y 次,则该元素在交集结果中出现 min(x, y)
次。
10.2 union
函数 union 用于求解两个集合的 并集 ,示例:
val seq1 = Seq(1, 2, 3, 3) val seq2 = Seq(2, 3, 4, 5) seq1.union(seq2) // 输出:List(1, 2, 3, 3, 2, 3, 4, 5)
并集等价于 ++
操作。
10.3 diff
函数 diff 用于求解两个集合的 差集 ,示例:
val seq1 = Seq(1, 2, 3, 3) val seq2 = Seq(2, 3, 4, 5) seq1.diff(seq2) // 输出:List(1, 3)
注意:如果两个集合包含重复元素,假设该元素在集合 A 中出现 x 次,在集合 B 中出现 y 次,则该元素在差集结果中出现 max(0, x - y)
次。
十一. 排列组合
11.1 permutations
函数 permutations 用于获取一个 Seq 对象中元素的全排列,示例:
val seq = Seq(1, 1, 3) seq.permutations.foreach(println)
输出:
List(1, 1, 3) List(1, 3, 1) List(3, 1, 1)
注意:如果输入集合中包含重复元素,则在全排列时会出现重复的排列,函数 permutations 会对结果去重。
11.2 combinations
函数 combinations 按照顺序从 Seq 对象中选取指定个数的元素进行组合,下面的示例按照顺序每次选择 3 个元素构建组合:
val seq = Seq(1, 2, 3, 4) seq.combinations(3).foreach(println)
输出:
List(1, 2, 3) List(1, 2, 4) List(1, 3, 4) List(2, 3, 4)
十二. 检查两个序列对应的元素是否满足给定条件
12.1 corresponds
函数 corresponds 用于接收一个序列 that 作为参数,并接收一个谓词 (A,B) => Boolean
,函数会按照下标对两个集合中的元素逐一比对是否满足给定条件,如果全部满足则返回 true,函数定义如下:
def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean
示例:
val seq1 = Seq(1, 2, 3) val seq2 = Seq.range(2, 7, 2) seq1.corresponds(seq2)(_ * 2 == _) // 输出:true
以上所述就是小编给大家介绍的《Scala 集合:Seq API》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Scala 中的集合(二):集合性能比较
- Scala 中的集合(二):集合性能比较
- 《面试知识,工作可待:集合篇》:Java 集合面试知识大全
- 如何对集合对象求合计,然后追加在该集合对象中
- MongoDB指南---14、特殊的索引和集合:固定集合、TTL索引、全文本索引
- Python 集合相关操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Producter 让产品从0到1
周楷雯 / 人民邮电出版社 / 2016-12-25 / CNY 69.00
这是一本以App Store首页推荐的成功App为例阐述如何完成一款App产品的设计、开发和营销的书。在这本书之后,作者的《一炷香》和《字里行间》两款产品也接连被App Store首页推荐。 《Producter 让产品从0到1》从产品的设计、产品的实现、产品的迭代、产品的营销、产品的进阶等几个角度,全面讲解了产品设计的基本原则、设计的重要性、设计的感觉、实用的设计工具、简单的iOS开发、产......一起来看看 《Producter 让产品从0到1》 这本书的介绍吧!