Scala 数组、集合函数汇总统计
Scala 语言中提供的数组是用来存储固定大小的同类型元素,数组对于每一门编辑应语言来说都是重要的数据结构之一。
声明数组变量并不是声明 number0、number1、…、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。
数组的第一个元素索引为0,最后一个元素的索引为元素总数减1。
| 函数 | 函数功能说明 |
|---|---|
| ++ | 合并集合,并返回一个新的数组,新数组包含左右两个集合的内容 |
| ++: | 这个方法同上一个方法类似,两个加号后面多了一个冒号,但是不同的是右边操纵数的类型决定着返回结果的类型 |
| +: | 在数组前面添加一个元素,并返回新的数组对象 |
| :+ | 在数组后面添加一个元素,并返回新的数组对象 |
| /: | 对数组中所有的元素从左向右遍历,进行相同的迭代操作,foldLeft 的简写 |
| :\ | 对数组中所有的元素从右向左遍历,进行相同的迭代操作,foldRight 的简写 |
| addString(b) | 将数组中的元素逐个添加到 StringBuilder 中 |
| addString(b, sep) | 将数组中的元素逐个添加到 StringBuilder 中,每个元素用 sep 分隔符分开 |
| aggregate | 聚合计算,aggregate 是柯里化方法,参数是两个方法 |
| apply | 获取指定索引处的元素 |
| canEqual | 判断两个对象是否可以进行比较 |
| charAt | 获取 index 索引处的字符,这个方法会执行一个隐式的转换,将 Array[T] 转换为 ArrayCharSequence,只有当 T 为 Char 类型时,这个转换才会发生 |
| clone | 创建一个副本 |
| collect | 通过执行一个并行计算(偏函数),得到一个新的数组对象 |
| collectFirst | 在序列中查找第一个符合偏函数定义的元素,并执行偏函数计算 |
| combinations | combinations 表示组合,这个排列组合会选出所有包含字符不一样的组合,但不考虑顺序,对于 “abc”、“cba”,视为相同组合,参数 n 表示序列长度,就是几个字符为一组 |
| contains | 判断序列中是否包含指定对象 |
| containsSlice | 判断当前序列中是否包含另一个序列 |
| copyToArray(xs) | 将当前数组元素复制到另一个数组中 |
| copyToArray(xs, start) | 将当前数组元素复制到另一个数组中,从 start 位置开始复制 |
| copyToArray(xs, start, len) | 将当前数组元素复制到另一个数组中,从 start 位置开始复制,长度为 len |
| copyToBuffer | 将数组中的元素复制到 Buffer 中 |
| corresponds | 判断两个序列的长度以及对应位置元素是否符合某个条件。如果两个序列具有相同的元素数量并且 p(x, y)=true,则返回 true |
| count | 统计符合条件的元素个数 |
| diff | 计算当前数组与另一个数组的差集,即将当前数组中没有在另一个数组中出现的元素返回 |
| distinct | 去除当前集合中重复的元素,只保留一个 |
| drop | 将当前数组中前 n 个元素去除,返回一个新数组 |
| dropRight | 功能同 drop,去掉尾部的 n 个元素 |
| dropWhile | 去除当前数组中符合条件的元素,返回剩余的数组,这个需要一个条件,就是从当前数组的第一个元素起,就要满足条件,直到碰到第一个不满足条件的元素结束(即使后面还有符合条件的元素),否则返回整个数组 |
| endsWith | 判断当前序列是否以某个序列结尾 |
| exists | 判断当前数组是否包含符合条件的元素 |
| filter | 取得当前数组中符合条件的元素,组成新的数组返回 |
| find | 查找第一个符合条件的元素,返回 Option |
| flatMap | 对当前序列的每个元素进行操作,结果放入新序列返回,参数要求是 GenTraversableOnce 及其子类 |
| flatten | 扁平化,将二维数组的所有元素组合在一起,形成一个一维数组返回 |
| fold | 对序列中的每个元素进行二元运算,和 aggregate 有类似的语义,但执行过程有所不同 |
| foldLeft | 从左到右计算,简写方式:def /:[B](z: B)(op: (B, T) ⇒ B): B |
| foldRight | 从右到左计算,简写方式:def :[B](z: B)(op: (T, B) ⇒ B): B |
| forall | 检测序列中的元素是否都满足条件 p,如果序列为空,则返回 true |
| foreach | 遍历序列中的元素,进行 f 操作 |
| groupBy | 按条件分组,条件由 f 匹配,返回值是 Map 类型,每个 key 对应一个数组 |
| grouped | 按指定数量分组,每组有 size 个元素,返回一个迭代器 |
| hasDefiniteSize | 检测序列是否存在有限的长度,对应 Stream 这样的流数据则返回 false |
| head | 返回序列的第一个元素,如果序列为空,将引发错误 |
| headOption | 返回序列的第一个元素的 Option 类型对象,如果序列为空,则返回 None |
| indexOf(elem) | 返回元素 elem 在序列中第一次出现的索引 |
| indexOf(elem, from) | 返回元素 elem 在序列中第一次出现的索引,指定从索引 from 开始查找 |
| indexOfSlice(that) | 检测当前序列中是否包含序列 that,并返回第一次出现该序列的索引 |
| indexOfSlice(that, from) | 检测当前序列中是否包含另一个序列 that,指定从索引 from 开始查找,并返回第一次出现该序列的索引 |
| indexWherepp | 返回当前序列中第一个满足条件 p 的元素的索引 |
| indexWhere(p, from) | 返回当前序列中第一个满足条件 p 的元素的索引,指定从索引 from 开始查找 |
| indices | 返回当前序列索引集合 |
| init | 返回当前序列中不包含最后一个元素的序列 |
| inits | 对集合中的元素进行 init 迭代操作,该操作的返回值中, 第一个值是当前序列的副本,最后一个值为空,每一步都进行 init 操作,上一步的结果作为下一步的操作对象 |
| intersect | 取两个集合的交集 |
| isDefinedAt | 判断序列中是否存在指定索引 |
| isEmpty | 判断序列是否为空 |
| isTraversableAgain | 判断序列是否可以反复遍历,该方法是 GenTraversableOnce 中的方法,对于 Traversables 一般返回 true,对于 Iterators 返回 false,除非被复写 |
| iterator | 生成当前序列的迭代器 |
| last | 返回序列的最后一个元素,如果序列为空,将引发错误 |
| lastIndexOf(elem) | 返回元素 elem 在序列中最后一次出现的索引 |
| lastIndexOf(elem, end) | 返回元素 elem 在序列中最后一次出现的索引,指定在索引 end 之前(包括)的元素中查找 |
| lastIndexOfSlice(that) | 检测当前序列中是否包含序列 that,并返回最后一次出现该序列的索引 |
| lastIndexOfSlice(that, end) | 检测当前序列中是否包含序列 that,并返回最后一次出现该序列的索引,指定在索引 end 之前(包括)的元素中查找 |
| lastIndexWherepp | 返回当前序列中最后一个满足条件 p 的元素的索引 |
| lastIndexWhere(p, end) | 返回当前序列中最后一个满足条件 p 的元素的索引,指定在索引 end 之前(包括)的元素中查找 |
| lastOption | 返回序列的最后一个元素的 Option 类型对象,如果序列为空,则返回 None |
| length | 返回序列元素个数 |
| lengthCompare | 比较序列的长度和参数 len,返回序列的长度 - len |
| map | 对序列中的元素进行 f 操作,返回生成的新序列 |
| max | 返回序列中最大的元素 |
| maxBy | 返回序列中符合条件的第一个元素 |
| min | 返回序列中最小的元素 |
| minBy | 返回序列中不符合条件的第一个元素 |
| mkString | 将序列中所有元素拼接成一个字符串 |
| mkString(sep) | 将序列中所有元素拼接成一个字符串,以 sep 作为元素间的分隔符 |
| mkString(start, sep, end) | 将序列中所有元素拼接成一个字符串,以 start 开头,以 sep 作为元素间的分隔符,以 end 结尾 |
| nonEmpty | 判断序列是否不为空 |
| padTo | 填充序列,如果当前序列长度小于 len,那么新产生的序列长度是 len,多出的几个位值填充 elem,如果当前序列大于等于 len ,则返回当前序列 |
| par | 返回一个并行实现,产生的并行序列不能被修改 |
| partition | 按条件将序列拆分成两个数组,满足条件的放到第一个数组,其余的放到第二个数组,返回的是包含这两个数组的元组 |
| patch | 批量替换,从原序列的 from 处开始,后面的 replaced 个元素,将被替换成序列 that |
| permutations | permutations 表示排列,这个排列组合会选出所有排列顺序不同的字符组合,permutations 与 combinations 不同的是,相同的组合考虑排列,对于 “abc”、“cba”,视为不同的组合 |
| prefixLength | 给定一个条件 p,返回一个前置数列的长度,这个数列中的元素都满足 p |
| product | 返回所有元素乘积的值 |
| reduce | 同 fold,不需要初始值 |
| reduceLeft | 同 foldLeft,从左向右计算,不需要初始值 |
| reduceRight | 同 foldRight,从右向左计算,不需要初始值 |
| reduceLeftOption | 同 reduceLeft,返回 Option |
| reduceRightOption | 同 reduceRight,返回 Option |
| reverse | 反转序列 |
| reverseIterator | 生成反向迭代器 |
| reverseMap | 同 map,方向相反 |
| sameElements | 判断两个序列是否顺序和对应位置上的元素都一样 |
| scan | 同 fold,scan 会把每一步的计算结果放到一个新的集合中返回,而 fold 返回的是最后的结果 |
| scanLeft | 同 foldLeft,从左向右计算,每一步的计算结果放到一个新的集合中返回 |
| scanRight | 同 foldRight,从右向左计算,每一步的计算结果放到(从右向左放)一个新的集合中返回 |
| segmentLength | 从序列的 from 开始向后查找,返回满足条件 p 的连续元素的长度,只返回第一个 |
| seq | 产生一个引用当前序列的 sequential 视图 |
| size | 返回序列元素个数,同 length |
| slice | 返回当前序列中从 from 到 until 之间的序列,不包括 until 处的元素 |
| sliding(size) | 滑动,从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素个数不够 size 时,则结束 |
| sliding(size, step) | 从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素个数不够 size 时,则结束。该方法可以设置步长 step,每一组元素组合完后,下一组从上一组起始元素位置 + step 后的位置处开始 |
| sortBy | 按指定的排序规则对序列排序 |
| sorted | 使用默认的排序规则对序列排序 |
| span | 将序列拆分成两个数组,从第一个元素开始,直到第一个不满足条件的元素为止,其中的元素放到第一个数组,其余的放到第二个数组,返回的是包含这两个数组的元组 |
| splitAt | 从指定位置开始,把序列拆分成两个数组 |
| startsWith(that) | 判断序列是否以某个序列开始 |
| startsWith(that, offset) | 判断序列从指定偏移处是否以某个序列开始 |
| stringPrefix | 返回 toString 结果的前缀 |
| subSequence | 返回 start 和 end 间的字符序列,不包含 end 处的元素 |
| sum | 序列求和,元素需为 Numeric[T] 类型 |
| tail | 返回当前序列中不包含第一个元素的序列 |
| tails | 同 inits,每一步都进行 tail 操作 |
| take | 返回当前序列中,前 n 个元素组成的序列 |
| takeRight | 返回当前序列中,从右边开始,后 n 个元素组成的序列 |
| takeWhile | 返回当前序列中,从第一个元素开始,满足条件的连续元素组成的序列 |
| toArray | 将序列转换成 Array 类型 |
| toBuffer | 将序列转换成 Buffer 类型 |
| toIndexedSeq | 将序列转换成 IndexedSeq 类型 |
| toIterable | 将序列转换成可迭代的类型 |
| toIterator | 将序列转换成迭代器,同 iterator 方法 |
| toList | 将序列转换成 List 类型 |
| toMap | 将序列转转换成 Map 类型,需要被转化序列中包含的元素是 Tuple2 类型 |
| toSeq | 将序列转换成 Seq 类型 |
| toSet | 将序列转换成 Set 类型 |
| toStream | 将序列转换成 Stream 类型 |
| toVector | 将序列转换成 Vector 类型 |
| transpose | 矩阵转置,二维数组行列转换 |
| union | 合并两个序列,同操作符 ++ |
| unzip | 将含有两个二元组的数组,每个元组的第一个元素组成一个数组,第二个元素组成一个数组,返回包含这两个数组的元组 |
| unzip3 | 将含有三个三元组的数组,每个元组的第一个元素组成一个数组,第二个元素组成一个数组,第三个元素组成一个数组,返回包含这三个数组的元组 |
| update | 将序列中 i 索引处的元素更新为 x |
| updated | 将序列中 i 索引处的元素更新为 x,并返回替换后的数组 |
| view | 返回当前序列中从 from 到 until 之间的序列,不包括 until 处的元素 |
| withFilter | 根据条件 p 过滤元素 |
| zip | 将两个序列对应位置上的元素组成一个元组数组,要求两个序列长度相同 |
| zipAll | 同 zip ,但是允许两个序列长度不同,不足的自动填充,如果当前序列短,不足的元素填充为 thisElem,如果 that 序列短,填充为 thatElem |
| zipWithIndex | 序列中的每个元素和它的索引组成一个元组数组 |
package zb.kb11
import scala.collection.mutable.ArrayBuffer
object ArrayTest {
def main(args: Array[String]): Unit = {
// val arr=Array(1,2,3,4,5)
// val newArr=arr.map(_*2) //所有数组*2
// println(newArr.mkString(",")) //转换成string
// println(newArr.mkString("(",",",")")) //拼接字符串
// ++ 合并集合,并返回一个新的数组,新数组包含两个集合的内容
// val a=Array(1,2)
// val b=Array(3,4)
// val c =a ++ b
// println(c.mkString(","))
// ++: 返回结果为合集,但是返回类型为右边的类型
// val a=List(1,2)
// val b=scala.collection.mutable.LinkedList(3,4)
// val c=a ++: b
// println(c.getClass.getName())
// +: 在数组前面添加一个元素
// val a=List(1,2)
// val b=0 +: a
// println(b.mkString(","))
//:+ 在数组后面添加一个元素
// val a=List(1,2)
// val b= a :+ 3
// println(b.mkString(","))
// /: 对数组从左向右遍历 foldLeft的简写
// val a = List(1, 2, 3, 4)
// val b = (10 /: a) (_ + _) // (((10+1)+2)+3)+4
// val c = (10 /: a) (_ * _) // (((10*1)*2)*3)*4
// println("b: " + b) // b: 20
// println("c: " + c) // c: 240
// \: 对数组中所有的元素从右向左遍历 foldRight 的简写
// val a = List(1, 2, 3, 4)
// val b = (a :\ 10) (_ - _) // 1-(2-(3-(4-10)))
// val c = (a :\ 10) (_ * _) // 1*(2*(3*(4*10)))
// println("b: " + b) // b: -8
// println("c: " + c) // c: 240
//addString(b) 将数组逐个添加到StringBuider中
// val a=List(1,2,3,4)
// val b=new StringBuilder()
// a.addString(b)
// println(b) //1234
//addString(b,sep) 逐个添加后用sep分隔符分开
// val a = List(1, 2, 3, 4)
// val b = new StringBuilder()
// a.addString(b, ",")
// println(b) // 1,2,3,4
//aggregate 柯里化方法,参数是两个方法
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
// def combine(m: Int, n: Int): Int = {
// val s = "com_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
//
// val a = List(1, 2, 3, 4)
//
// val b = a.aggregate(5)(seqno, combine) // 不分区
// println("b = " + b)
// /**
// * seq_exp = 5 + 1
// * seq_exp = 6 + 2
// * seq_exp = 8 + 3
// * seq_exp = 11 + 4
// * b = 15
// */
//
// val c = a.par.aggregate(5)(seqno, combine) // 分区
// println("c = " + c)
// /**
// * seq_exp = 5 + 3
// * seq_exp = 5 + 2
// * seq_exp = 5 + 4
// * seq_exp = 5 + 1
// * com_exp = 6 + 7
// * com_exp = 8 + 9
// * com_exp = 13 +17
// * c = 30
// */
//
//利用aggregate算平均值
// val aa=List(Array(3,5,2,4),Array(7,8,1,2,9),Array(3,5,2,4),Array(7,8,1,2,9),Array(3,5,2,4),Array(7,8,1,2,9))
//
// def seqno(m:(Int,Int),n:Array[Int]):(Int,Int)={
// (m._1+n.sum,m._2+n.size)
// }
//
// def combin(m:(Int,Int),n:(Int,Int)):(Int,Int)={
// (m._1+n._1,m._2+n._2)
// }
//
//
// var s= aa.par.aggregate(0,0)(seqno,combin)
// var avg=s._1/s._2.toDouble
// println(avg)
// }
//apply 获取指定索引处的元素
// val a = List(1, 2, 3, 4)
// val b = a.apply(1) // a.apply(i) 同 a(i)
// println(b) // 2
//canEqual 判断两个对象是否可以进行比较
// val a = List(1, 2, 3, 4)
// val b = Array('a', 'b', 'c')
// println(a.canEqual(b)) // true
//charAt 获取 index 索引处的字符,这个方法会执行一个隐式的转换,将 Array[T] 转换为 ArrayCharSequence,只有当 T 为 Char 类型时,这个转换才会发生
// val chars = Array('a', 'b', 'c')
// println(chars.charAt(0))
//clone 创建一个副本
// val a = Array(1, 2, 3, 4)
// val b = a.clone()
// println(b.mkString(",")) // 1,2,3,4
//collect 通过执行一个并行计算(偏函数),得到一个新的数组对象
// val fun: PartialFunction[Char, Char] = {
// case 'a' => 'A'
// case x => x
// }
// val a = Array('a', 'b', 'c')
// val b = a.collect(fun)
// println(b.mkString(",")) // A,b,c
//collectFirst 序列中查找第一个符合偏函数定义的元素,并执行偏函数计算
// val fun:PartialFunction[Any,Int]={
// case x:Int =>x*100
// }
// val a=Array(1,'a',"b")
//// val b=a.collectFirst(fun)
// val b = a.collectFirst({ case x: Int => x * 100 }) //简单写法
// println(b)
//combinations combinations 表示组合,这个排列组合会选出所有包含字符不一样的组合,但不考虑顺序,对于 “abc”、“cba”,视为相同组合,参数 n 表示序列长度,就是几个字符为一组
// val a = Array("a", "b", "c")
// val b = a.combinations(2)
//// b.foreach(x => println(x.mkString(",")))
// b.foreach(x=>{println(x.getClass.getName);println(x.mkString("\n"))})
// /**
// * a,b
// * a,c
// * b,c
// */
//contains 判断序列中是否包含指定对象
// val a=List(1,2,3,4)
// println(a.contains(1))
//containsSlice 判断当前序列中是否包含另一个序列
// val a = List(1, 2, 3, 4)
// val b = List(2, 3)
// println(a.containsSlice(b)) // true
// copyToArray(xs) 将当前数组元素复制到另一个数组中
// val a = Array(1, 2, 3)
// val b: Array[Int] = new Array(5)
// a.copyToArray(b)
// println(b.mkString(",")) // 1,2,3,0,0
//copyToArray(xs, start) 将当前数组元素复制到另一个数组中,从 start 位置开始复制
// val a = Array(1, 2, 3)
// val b: Array[Int] = new Array(5)
// a.copyToArray(b, 1)
// println(b.mkString(",")) // 0,1,2,3,0
//copyToArray(xs, start, len) 将当前数组元素复制到另一个数组中,从 start 位置开始复制,长度为 len
// val a = Array(1, 2, 3)
// val b: Array[Int] = new Array(5)
// a.copyToArray(b, 1, 2)
// println(b.mkString(",")) // 0,1,2,0,0
//copyToBuffer 将数组中的元素复制到 Buffer 中
// val a = Array(1, 2, 3, 4)
// val b: ArrayBuffer[Int] = ArrayBuffer()
// a.copyToBuffer(b)
// println(b.mkString(",")) // 1,2,3,4
//corresponds 判断两个序列的长度以及对应位置元素是否符合某个条件。如果两个序列具有相同的元素数量并且 p(x, y)=true,则返回 true
// val a = Array(1, 2, 3, 4)
// val b = Array(5, 6, 7, 8)
// println(a.corresponds(b)(_ < _)) // true
//count 统计符合条件的元素个数
// val a = Array(1, 2, 3, 4)
// println(a.count(x => x > 2)) // 2
//diff 计算当前数组与另一个数组的差集,即将当前数组中没有在另一个数组中出现的元素返回
// val a = Array(1, 2, 3, 4)
// val b = Array(3, 4, 5, 6)
// val c = a.diff(b)
// println(c.mkString(",")) // 1,2
//distinct 去除当前集合中重复的元素,只保留一个
// val a = Array(1, 2, 2, 3, 4, 4)
// val b = a.distinct
// println(b.mkString(",")) // 1,2,3,4
//drop 将当前数组中前 n 个元素去除,返回一个新数组
// val a = Array(1, 2, 3, 4)
// val b = a.drop(2)
// println(b.mkString(",")) // 3,4
//dropRight 功能同 drop,去掉尾部的 n 个元素
// val a = Array(1, 2, 3, 4)
// val b = a.dropRight(2)
// println(b.mkString(",")) // 1,2
//dropWhile 去除当前数组中符合条件的元素,返回剩余的数组,这个需要一个条件,就是从当前数组的第一个元素起,就要满足条件,直到碰到第一个不满足条件的元素结束(即使后面还有符合条件的元素),否则返回整个数组
// val a = Array(1, 2, 3, 4)
// val b = a.dropWhile(x => x < 2)
// println(b.mkString(",")) // 2,3,4
//endsWith 判断当前序列是否以某个序列结尾
// val a = Array(1, 2, 3, 4)
// val b = Array(3, 4)
// println(a.endsWith(b)) // true
//exists 判断当前数组是否包含符合条件的元素
// val a = Array(1, 2, 3, 4)
// println(a.exists(x => x == 3)) // true
// println(a.exists(x => x == 30)) // false
//filter 取得当前数组中符合条件的元素,组成新的数组返回
// val a = Array(1, 2, 3, 4)
// val b = a.filter(x => x > 2)
// val c=a.filterNot(x=>x>2)
// println(b.mkString(",")) // 3,4
// println(c.mkString(",")) // 3,4
//find 查找第一个符合条件的元素,返回 Option
// val a = Array(1, 2, 3, 4)
// val b = a.find(x => x > 2)
// println(b) // Some(3)
//flatMap 对当前序列的每个元素进行操作,结果放入新序列返回,参数要求是 GenTraversableOnce 及其子类
// val a = Array(1, 2, 3, 4)
// val b = a.flatMap(x => 1 to x)
// println(b.mkString(","))
// /**
// * 1,1,2,1,2,3,1,2,3,4
// * 从 1 开始,分别对集合 a 中的每个元素生成一个递增序列,过程如下
// * 1
// * 1,2
// * 1,2,3
// * 1,2,3,4
// */
// val e= Array(1,2,3,4)
// val f=e.flatMap(y => y to y)
// println(f.mkString(","))
//flatten 扁平化,将二维数组的所有元素组合在一起,形成一个一维数组返回
// val a = Array(Array(1, 2, 3), Array(4, 5, 6))
// val b = a.flatten
// println(b.mkString(",")) // 1,2,3,4,5,6
//fold 对序列中的每个元素进行二元运算,和 aggregate 有类似的语义,但执行过程有所不同
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
//
// val a = Array(1, 2, 3, 4)
//
// val b = a.fold(5)(seqno) // 不分区
// println("b = " + b)
// /**
// * seq_exp = 5 + 1
// * seq_exp = 6 + 2
// * seq_exp = 8 + 3
// * seq_exp = 11 + 4
// * b = 15
// */
//
// val c = a.par.fold(5)(seqno) // 分区
// println("c = " + c)
// /**
// * seq_exp = 5 + 3
// * seq_exp = 5 + 2
// * seq_exp = 5 + 4
// * seq_exp = 5 + 1
// * seq_exp = 6 + 7
// * seq_exp = 8 + 9
// * seq_exp = 13 + 17
// * c = 30
// */
//foldLeft 从左到右计算,简写方式:def /:[B](z: B)(op: (B, T) ⇒ B): B
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
// val a = Array(1, 2, 3, 4)
//
// val b = a.foldLeft(5)(seqno) // 简写: (5 /: a)(_ + _)
// println("b = " + b)
// /**
// * seq_exp = 5 + 1
// * seq_exp = 6 + 2
// * seq_exp = 8 + 3
// * seq_exp = 11 + 4
// * b = 15
// */
//
//foldRight 从右到左计算,简写方式:def :[B](z: B)(op: (T, B) ⇒ B): B
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
// val a = Array(1, 2, 3, 4)
//
// val b = a.foldRight(5)(seqno) // 简写: (a :\ 5)(_ + _)
// println("b = " + b)
// /**
// * seq_exp = 4 + 5
// * seq_exp = 3 + 9
// * seq_exp = 2 + 12
// * seq_exp = 1 + 14
// * b = 15
// */
//forall 检测序列中的元素是否都满足条件 p,如果序列为空,则返回 true
// val a = Array(1, 2, 3, 4)
// println(a.forall(x => x > 0)) // true
// println(a.forall(x => x > 2)) // false
//foreach 遍历序列中的元素,进行 f 操作
// val a = Array(1, 2, 3, 4)
// a.foreach(x => println(x * 10))
// /**
// * 10
// * 20
// * 30
// * 40
// */
//groupBy 按条件分组,条件由 f 匹配,返回值是 Map 类型,每个 key 对应一个数组
// val a = Array(1, 2, 3, 4)
// val b = a.groupBy(x => x match {
// case x if (x < 3) => "small"
// case _ => "big"
// })
// b.foreach(x => println(x._1 + ": " + x._2.mkString(",")))
// /**
// * small: 1,2
// * big: 3,4
// */
//grouped 按指定数量分组,每组有 size 个元素,返回一个迭代器
// val a=Array(1,2,3,4)
// val b=a.grouped(3).toList
// b.foreach(x=>println(x.mkString("-")))
//hasDefiniteSize 检测序列是否存在有限的长度,对应 Stream 这样的流数据则返回 false
// val a = Array(1, 2, 3, 4)
// println(a.hasDefiniteSize) // true
//head 返回序列的第一个元素,如果序列为空,将引发错误
// val a=Array(1,2,3,4)
// println(a.head)
//headOption 返回序列的第一个元素的 Option 类型对象,如果序列为空,则返回 None
// val a = Array(1, 2, 3, 4)
// println(a.headOption) // Some(1)
//indexOf(elem) 返回元素 elem 在序列中第一次出现的索引
// val a=Array(1,3,2,3,4)
// println(a.indexOf(3))
//indexOf(elem,from) 返回元素 elem 在序列中第一次出现的索引,指定从索引 from 开始查找
// val a = Array(1, 3, 2, 3, 4)
// println(a.indexOf(3, 2)) // 3
//indexOfSlice(that) 检测当前序列中是否包含序列 that,并返回第一次出现该序列的索引
// val a = Array(1, 2, 3, 2, 3, 4)
// val b = Array(2, 3)
// println(a.indexOfSlice(b)) // 1
//indexOfSlice(that, from) 检测当前序列中是否包含另一个序列 that,指定从索引 from 开始查找,并返回第一次出现该序列的索引
// val a = Array(1, 2, 3, 2, 3, 4)
// val b = Array(2, 3)
// println(a.indexOfSlice(b, 2)) // 3
//indexWhere(p) 返回当前序列中第一个满足条件 p 的元素的索引
// val a = Array(1, 2, 3, 4)
// println(a.indexWhere(x => x > 2)) // 2
//indexWhere(p, from) 返回当前序列中第一个满足条件 p 的元素的索引,指定从索引 from 开始查找
// val a = Array(1, 2, 3, 4)
// println(a.indexWhere(x => x > 2, 3)) // 3
//indices 返回当前序列索引集合
// val a = Array(1, 2, 3, 4)
// val b = a.indices
// println(b.mkString(",")) // 0,1,2,3
//init 返回当前序列中不包含最后一个元素的序列
// val a = Array(1, 2, 3, 4)
// val b = a.init
// println(b.mkString(",")) // 1,2,3
//inits 对集合中的元素进行 init 迭代操作,该操作的返回值中, 第一个值是当前序列的副本,最后一个值为空,每一步都进行 init 操作,上一步的结果作为下一步的操作对象
// val a = Array(1, 2, 3, 4)
// val b = a.inits.toList
// for (i <- 0 until b.length) {
// val s = "第 %d 个值: %s"
// println(s.format(i + 1, b(i).mkString(",")))
// }
// /**
// * 第 1 个值: 1,2,3,4
// * 第 2 个值: 1,2,3
// * 第 3 个值: 1,2
// * 第 4 个值: 1
// * 第 5 个值:
// */
//intersect 取两个集合的交集
// val a = Array(1, 2, 3, 4)
// val b = Array(3, 4, 5, 6)
// val c = a.intersect(b)
// println(c.mkString(",")) // 3,4
//isDefinedAt 判断序列中是否存在指定索引
// val a = Array(1, 2, 3, 4)
// println(a.isDefinedAt(1)) // true
// println(a.isDefinedAt(10)) // false
//isEmpty 判断序列是否为空
// val a = Array(1, 2, 3, 4)
// val b = new Array[Int](0)
// println(b.isEmpty) // true
// println(a.isEmpty) // false
//isTraversableAgain 判断序列是否可以反复遍历,该方法是 GenTraversableOnce 中的方法,对于 Traversables 一般返回 true,对于 Iterators 返回 false,除非被复写
// val a = Array(1, 2, 3, 4)
// val b = a.iterator
// println(a.isTraversableAgain) // true
// println(b.isTraversableAgain) // false
//iterator 生成当前序列的迭代器
// val a = Array(1, 2, 3, 4)
// val b = a.iterator
// println(b.mkString(",")) // 1,2,3,4
//last 返回序列的最后一个元素,如果序列为空,将引发错误
// val a = Array(1, 2, 3, 4)
// println(a.last) // 4
//lastIndexOf(elem) 返回元素 elem 在序列中最后一次出现的索引
// val a = Array(1, 3, 2, 3, 4)
// println(a.lastIndexOf(3)) // 3
//lastIndexOf(elem, end) 返回元素 elem 在序列中最后一次出现的索引,指定在索引 end 之前(包括)的元素中查找
// val a = Array(1, 3, 2, 3, 4)
// println(a.lastIndexOf(3, 2)) // 1
// //lastIndexOfSlice(that) 检测当前序列中是否包含序列 that,并返回最后一次出现该序列的索引
// val a = Array(1, 2, 3, 2, 3, 4)
// val b = Array(2, 3)
// println(a.lastIndexOfSlice(b)) // 3
//lastIndexWhere(p) 返回当前序列中最后一个满足条件 p 的元素的索引
// val a = Array(1, 2, 3, 4)
// println(a.lastIndexWhere(x => x > 2)) // 3
//lastIndexWhere(p, end) 返回当前序列中最后一个满足条件 p 的元素的索引,指定在索引 end 之前(包括)的元素中查找
// val a = Array(1, 2, 3, 4)
// println(a.lastIndexWhere(x => x > 2, 2)) // 2
//lastOption 返回序列的最后一个元素的 Option 类型对象,如果序列为空,则返回 None
// val a = Array(1, 2, 3, 4)
// println(a.lastOption) // Some(4)
//length 返回序列元素个数
// val a = Array(1, 2, 3, 4)
// println(a.length) // 4
//lengthCompare 比较序列的长度和参数 len,返回序列的长度 - len
// val a = Array(1, 2, 3, 4)
// println(a.lengthCompare(3)) // 1
// println(a.lengthCompare(4)) // 0
// println(a.lengthCompare(5)) // -1
//map 对序列中的元素进行 f 操作,返回生成的新序列
// val a = Array(1, 2, 3, 4)
// val b = a.map(x => x * 10)
// println(b.mkString(",")) // 10,20,30,40
//max 返回序列中最大的元素
// val a = Array(1, 2, 3, 4)
// println(a.max) // 4
//maxBy 返回序列中符合条件的第一个元素
// val a = Array(1, 2, 3, 4)
// println(a.maxBy(x => x > 2)) // 3
//min 返回序列中最小的元素
// val a = Array(1, 2, 3, 4)
// println(a.min) // 1
//minBy 返回序列中不符合条件的第一个元素
// val a = Array(1, 2, 3, 4)
// println(a.minBy(x => x < 2)) // 2
//mkString 将序列中所有元素拼接成一个字符串
// val a = Array(1, 2, 3, 4)
// println(a.mkString) // 1234
//mkString(sep) 将序列中所有元素拼接成一个字符串,以 sep 作为元素间的分隔符
// val a = Array(1, 2, 3, 4)
// println(a.mkString(",")) // 1,2,3,4
//mkString(start, sep, end) 将序列中所有元素拼接成一个字符串,以 start 开头,以 sep 作为元素间的分隔符,以 end 结尾
// val a = Array(1, 2, 3, 4)
// println(a.mkString("(", ",", ")")) // (1,2,3,4)
//nonEmpty 判断序列是否不为空
// val a = Array(1, 2, 3, 4)
// val b = new Array[Int](0)
// println(a.nonEmpty) // true
// println(b.nonEmpty) // false
//padTo 填充序列,如果当前序列长度小于 len,那么新产生的序列长度是 len,多出的几个位值填充 elem,如果当前序列大于等于 len ,则返回当前序列
// val a = Array(1, 2, 3, 4)
// val b = a.padTo(7, 8) //填充一个长度为 7 的序列,不足位补 8
// println(b.mkString(",")) // 1,2,3,4,8,8,8
//par 返回一个并行实现,产生的并行序列不能被修改
// val a = Array(1, 2, 3, 4)
// val b = a.par
// println(b.mkString(",")) // 1,2,3,4
//partition 按条件将序列拆分成两个数组,满足条件的放到第一个数组,其余的放到第二个数组,返回的是包含这两个数组的元组
// val a = Array(1, 2, 3, 4)
// val b: (Array[Int], Array[Int]) = a.partition(x => x % 2 == 0)
// println("偶数: " + b._1.mkString(",")) // 偶数: 2,4
// println("奇数: " + b._2.mkString(",")) // 奇数: 1,3
//patch 批量替换,从原序列的 from 处开始,后面的 replaced 个元素,将被替换成序列 that
// val a = Array(1, 2, 3, 4)
// val b = Array(7, 8, 9)
// val c = a.patch(1, b, 2) //从 a 的第二个元素开始,取两个元素,即 2 和 3 ,将这两个元素替换为序列 b
// println(c.mkString(",")) // 1,7,8,9,4
//permutations permutations 表示排列,这个排列组合会选出所有排列顺序不同的字符组合,permutations 与 combinations 不同的是,相同的组合考虑排列,对于 “abc”、“cba”,视为不同的组合
// val a = Array("a", "b", "c")
// val b = a.permutations.toList
// b.foreach( x => println(x.mkString(",")))
// /**
// * a,b,c
// * a,c,b
// * b,a,c
// * b,c,a
// * c,a,b
// * c,b,a
// */
//prefixLength 给定一个条件 p,返回一个前置数列的长度,这个数列中的元素都满足 p
// val a = Array(1, 2, 3, 4)
// println(a.prefixLength(x => x < 3)) // 2 不满足条件的前一个值
//product 返回所有元素乘积的值
// val a = Array(1, 2, 3, 4)
// println(a.product) // 1*2*3*4=24
//reduce 同fold, 不需要初始值
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
//
// val a = Array(1, 2, 3, 4)
// val b = a.reduce(seqno)
// println("b = " + b)
// /**
// * seq_exp = 1 + 2
// * seq_exp = 3 + 3
// * seq_exp = 6 + 4
// * b = 10
// */
//reduceLeft 同 foldLeft,从左向右计算,不需要初始值
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
// val a = Array(1, 2, 3, 4)
// val b = a.reduceLeft(seqno)
// println("b = " + b)
// /**
// * seq_exp = 1 + 2
// * seq_exp = 3 + 3
// * seq_exp = 6 + 4
// * b = 10
// */
//reduceRight 同 foldRight,从右向左计算,不需要初始值
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
// val a = Array(1, 2, 3, 4)
// val b = a.reduceRight(seqno)
// println("b = " + b)
// /**
// * seq_exp = 3 + 4
// * seq_exp = 2 + 7
// * seq_exp = 1 + 9
// * b = 10
// */
//reduceLeftOption 同 reduceLeft,返回 Option
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
// val a = Array(1, 2, 3, 4)
// val b = a.reduceLeftOption(seqno)
// println("b = " + b)
// /**
// * seq_exp = 1 + 2
// * seq_exp = 3 + 3
// * seq_exp = 6 + 4
// * b = Some(10)
// */
//
//reduceRightOption 同 reduceRight,返回 Option
// def seqno(m: Int, n: Int): Int = {
// val s = "seq_exp = %d + %d"
// println(s.format(m, n))
// m + n
// }
// val a = Array(1, 2, 3, 4)
// val b = a.reduceRightOption(seqno)
// println("b = " + b)
// /**
// * seq_exp = 3 + 4
// * seq_exp = 2 + 7
// * seq_exp = 1 + 9
// * b = Some(10)
// */
//reverse 反转序列
// val a = Array(1, 2, 3, 4)
// val b = a.reverse
// println(b.mkString(",")) // 4,3,2,1
//reverseIterator 生成反向迭代器
// val a = Array(1, 2, 3, 4)
// val b = a.reverseIterator
// b.foreach(x => print(x + " ")) // 4 3 2 1
//reverseMap 同 map,方向相反
// val a = Array(1, 2, 3, 4)
// val b = a.reverseMap(x => x * 10)
// println(b.mkString(",")) // 40,30,20,10
//sameElements 判断两个序列是否顺序和对应位置上的元素都一样
// val a = Array(1, 2, 3, 4)
//
// val b = Array(1, 2, 3, 4)
// println(a.sameElements(b)) // true
//
// val c = Array(1, 3, 2, 4)
// println(a.sameElements(c)) // false
//scan 同 fold,scan 会把每一步的计算结果放到一个新的集合中返回,而 fold 返回的是最后的结果
// val a = Array(1, 2, 3, 4)
// val b = a.scan(5)(_ + _)
// println(b.mkString(",")) // 5,6,8,11,15
//scanLeft 同 foldLeft,从左向右计算,每一步的计算结果放到一个新的集合中返回
// val a = Array(1, 2, 3, 4)
// val b = a.scanLeft(5)(_ + _)
// println(b.mkString(",")) // 5,6,8,11,15
//scanRight 同 foldRight,从右向左计算,每一步的计算结果放到(从右向左放)一个新的集合中返回
// val a = Array(1, 2, 3, 4)
// val b = a.scanRight(5)(_ + _)
// println(b.mkString(",")) // 15,14,12,9,5
//segmentLength 从序列的 from 开始向后查找,返回满足条件 p 的连续元素的长度,只返回第一个
// val a = Array(1, 2, 3, 1, 1, 1, 4)
// println(a.segmentLength(x => x < 3, 3)) // 3
//seq 产生一个引用当前序列的 sequential 视图
// val a = Array(1, 2, 3, 4)
// val b = a.seq
// println(b.mkString(",")) // 1,2,3,4
//size 返回序列元素个数,同 length
// val a = Array(1, 2, 3, 4)
// println(a.size) // 4
//slice 返回当前序列中从 from 到 until 之间的序列,不包括 until 处的元素
// val a = Array(1, 2, 3, 4)
// val b = a.slice(1, 3)
// println(b.mkString(",")) // 2,3
//sliding(size) 滑动,从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素个数不够 size 时,则结束
// val a = Array(1, 2, 3, 4, 5)
// val b = a.sliding(3).toList
// for (i <- 0 to b.length - 1) {
// val s = "第 %d 组: %s"
// println(s.format(i + 1, b(i).mkString(",")))
// }
// /**
// * 第 1 组: 1,2,3
// * 第 2 组: 2,3,4
// * 第 3 组: 3,4,5
// */
//sliding(size, step) 从第一个元素开始,每个元素和它后面的 size - 1 个元素组成一个数组,最终组成一个新的集合返回,当剩余元素个数不够 size 时,则结束。该方法可以设置步长 step,每一组元素组合完后,下一组从上一组起始元素位置 + step 后的位置处开始
// val a = Array(1, 2, 3, 4, 5)
// val b = a.sliding(3, 2).toList
// for (i <- 0 to b.length - 1) {
// val s = "第 %d 组: %s"
// println(s.format(i + 1, b(i).mkString(",")))
// }
// /**
// * 第 1 组: 1,2,3
// * 第 2 组: 3,4,5
// */
//sortBy 按指定的排序规则对序列排序
// val a = Array(3, 2, 1, 4)
//
// val b = a.sortBy(x => x) // 按 x 从小到大,即对原序列升序排列
// println("升序: " + b.mkString(",")) // 1,2,3,4
//
// val c = a.sortBy(x => 0 - x) // 按 -x 从小到大,即对原序列降序排列
// println("降序: " + c.mkString(",")) // 4,3,2,1
//sorted 使用默认的排序规则对序列排序
// val a = Array(3, 2, 1, 4)
// val b = a.sorted // 默认升序排列
// println(b.mkString(",")) // 1,2,3,4
//span 将序列拆分成两个数组,从第一个元素开始,直到第一个不满足条件的元素为止,其中的元素放到第一个数组,其余的放到第二个数组,返回的是包含这两个数组的元组
// val a = Array(1, 2, 3, 4)
// val b = a.span(x => x < 3)
// println(b._1.mkString(",")) // 1,2
// println(b._2.mkString(",")) // 3,4
//splitAt 从指定位置开始,把序列拆分成两个数组
// val a = Array(1, 2, 3, 4)
// val b = a.splitAt(2)
// println(b._1.mkString(",")) // 1,2
// println(b._2.mkString(",")) // 3,4
//startsWith 判断序列是否以某个序列开始
// val a = Array(1, 2, 3, 4)
// val b = Array(1, 2)
// println(a.startsWith(b)) // true
//startsWith(that, offset) 判断序列从指定偏移处是否以某个序列开始
// val a = Array(1, 2, 3, 4)
// val b = Array(2, 3)
// println(a.startsWith(b, 1)) // true
//stringPrefix 返回 toString 结果的前缀
// val a = Array(1, 2, 3, 4)
// println(a.toString()) // [I@3ab39c39
// println(a.stringPrefix) // [I
//subSequence 返回 start 和 end 间的字符序列,不包含 end 处的元素
// val a = Array('a', 'b', 'c', 'd')
// val b = a.subSequence(1, 3)
// println(b.toString) // bc
//sum 序列求和,元素需为 Numeric[T] 类型
// val a = Array(1, 2, 3, 4)
// println(a.sum) // 10
//tail 返回当前序列中不包含第一个元素的序列
// val a = Array(1, 2, 3, 4)
// val b = a.tail
// println(b.mkString(",")) // 2,3,4
//tails 同 inits,每一步都进行 tail 操作
// val a = Array(1, 2, 3, 4)
// val b = a.tails.toList
// for (i <- 0 until b.length) {
// val s = "第 %d 个值: %s"
// println(s.format(i + 1, b(i).mkString(",")))
// }
// /**
// * 第 1 个值: 1,2,3,4
// * 第 2 个值: 2,3,4
// * 第 3 个值: 3,4
// * 第 4 个值: 4
// * 第 5 个值:
// */
//take 返回当前序列中,前 n 个元素组成的序列
// val a = Array(1, 2, 3, 4)
// val b = a.take(3)
// println(b.mkString(",")) // 1,2,3
//takeRight 返回当前序列中,从右边开始,后 n 个元素组成的序列
// val a = Array(1, 2, 3, 4)
// val b = a.takeRight(3)
// println(b.mkString(",")) // 2,3,4
//takeWhile 返回当前序列中,从第一个元素开始,满足条件的连续元素组成的序列
// val a = Array(1, 2, 3, 4)
// val b = a.takeWhile(x => x < 3)
// print(b.mkString(",")) // 1,2
//toArray 将序列转换成 Array 类型
//toBuffer 将序列转换成 Buffer 类型
//toIndexedSeq 将序列转换成 IndexedSeq 类型
//tolterable 将序列转换成可迭代的类型
//toIterator 将序列转换成迭代器,同 iterator 方法
//toList 将序列转换成 List 类型
//toMap 将序列转转换成 Map 类型,需要被转化序列中包含的元素是 Tuple2 类型
//toSeq 将序列转换成 Seq 类型
//toSet 将序列转换成 Set 类型
//toStream 将序列转换成 Stream 类型
//toVector 将序列转换成 Vector 类型
//transpose 矩阵转置,二维数组行列转换
// val a = Array(Array("a", "b"), Array("c", "d"), Array("e", "f"))
// val b = a.transpose
// b.foreach(x => println((x.mkString(","))))
// /**
// * a,c,e
// * b,d,f
// */
//union 合并两个序列,同操作符 ++
// val a = Array(1, 2)
// val b = Array(3, 4)
// val c = a.union(b)
// println(c.mkString(",")) // 1,2,3,4
//unzip 将含有两个二元组的数组,每个元组的第一个元素组成一个数组,第二个元素组成一个数组,返回包含这两个数组的元组
// val chars = Array(("a", "b"), ("c", "d"))
// val b = chars.unzip
// println(b._1.mkString(",")) // a,c
// println(b._2.mkString(",")) // b,d
//unzip3 将含有三个三元组的数组,每个元组的第一个元素组成一个数组,第二个元素组成一个数组,第三个元素组成一个数组,返回包含这三个数组的元组
// val chars = Array(("a", "b", "x"), ("c", "d", "y"), ("e", "f", "z"))
// val b = chars.unzip3
// println(b._1.mkString(",")) // a,c,e
// println(b._2.mkString(",")) // b,d,f
// println(b._3.mkString(",")) // x,y,z
//update 将序列中 i 索引处的元素更新为 x
// val a = Array(1, 2, 3, 4)
// a.update(1, 7)
// println(a.mkString(",")) //1,7,3,4
//updated 将序列中 i 索引处的元素更新为 x,并返回替换后的数组
// val a = Array(1, 2, 3, 4)
// val b = a.updated(1, 7)
// println(b.mkString(",")) //1,7,3,4
//view 返回当前序列中从 from 到 until 之间的序列,不包括 until 处的元素
// val a = Array(1, 2, 3, 4)
// val b = a.view(1, 3)
// println(b.mkString(",")) // 2,3
//withFilter 根据条件 p 过滤元素
// val a = Array(1, 2, 3, 4)
// val b = a.withFilter(x => x > 2).map(x => x)
// println(b.mkString(",")) // 3,4
//zip 将两个序列对应位置上的元素组成一个元组数组,要求两个序列长度相同
// val a = Array(1, 2, 3, 4)
// val b = Array(4, 3, 2, 1)
// val c = a.zip(b)
// println(c.mkString(",")) // (1,4),(2,3),(3,2),(4,1)
//zipAll 同 zip ,但是允许两个序列长度不同,不足的自动填充,如果当前序列短,不足的元素填充为 thisElem,如果 that 序列短,填充为 thatElem
// val a = Array(1, 2, 3, 4, 5, 6, 7)
// val b = Array(5, 4, 3, 2, 1)
// val c = a.zipAll(b, 8, 9) // (1,5),(2,4),(3,3),(4,2),(5,1),(6,9),(7,9)
// println(c.mkString(","))
//
// val x = Array(1, 2, 3, 4)
// val y = Array(6, 5, 4, 3, 2, 1)
// val z = x.zipAll(y, 8, 9) // (1,6),(2,5),(3,4),(4,3),(8,2),(8,1)
// println(z.mkString(","))
//zipWithIndex 序列中的每个元素和它的索引组成一个元组数组
// val a = Array('a', 'b', 'c', 'd')
// val b = a.zipWithIndex
// println(b.mkString(",")) // (a,0),(b,1),(c,2),(d,3)
}
}
7015

被折叠的 条评论
为什么被折叠?



