Scala
元组(Tuple
)
-
元组(Tuple)本身是一个用于存储1到多个元素的容器,需要注意的是,元组不是集合!!!Scala中所有的集合都在
scala.collection
包,Tuple是scala
包下,但是集合操作中很多时候需要使用到元组 -
如果元素类型一致且元素有序可重复,可以使用序列(
Seq
);如果元素类型一致且元素无序不可重复,可以使用集合(Set
);如果元素是键值对形式,可以使用映射(Map
);如果元素类型不一致,那么使用元组Tuple
-
需要注意的是,Scala中提供了Tuple1~Tuple22,即元组中最多能够存储22个元素
-
之前学习的Map中存储的就是Tuple2,即
Map(tuple2, tuple2, ...)
。Tuple2又称之为对偶元组 -
元组定义格式
scalapackage com.fe.tuple object TupleDemo { def main(args: Array[String]): Unit = { // 定义格式 // 方式一 // 声明了Tuple3,元组定义好之后不可变 // 推荐使用这种方式 val t1: (String, Int, Char) = ("Bob", 15, 'm') println(t1) // 方式二 // val t2: Tuple4[String, Int, Double, Double] = Tuple4[String, Int, Double, Double]("Amy", 18, 165, 58) // val t2: Tuple4[String, Int, Double, Double] = Tuple4("Amy", 18, 165, 58) val t2: Tuple4[String, Int, Double, Double] = ("Amy", 18, 165, 58) println(t2) // 方式三 // 元组支持拆分 // val t3 = ("Sam", 15, "male") // 如果要获取元组中的元素,通过 _顺序 的形式来获取 // val mame = t3._1 // val age = t3._2 // val gender = t3._3 // val (name, age, gender) = t3 // 简化 val (name, age, gender) = ("Sam", 15, "male") println(name) println(age) println(gender) val (r1, r2, r3) = randTo100() println(r1) println(r2) println(r3) } def randTo100(): (Int, Int, Int) = { val r1 = (Math.random() * 100).toInt val r2 = (Math.random() * 100).toInt val r3 = (Math.random() * 100).toInt (r1, r2, r3) } }
-
遍历元组
scalapackage com.fe.tuple object TupleDemo2 { def main(args: Array[String]): Unit = { // 遍历元组 val t = ("Bob", 10, "male", 4, 6, 152.2, 50.3, "北京") // 产生迭代器 - 将元组中的所有的元素放入Iterator中返回 val it: Iterator[Any] = t.productIterator // while(it.hasNext) println(it.next()) // for (elem <- it) println(elem) it.foreach(println) // 根据元素类型来进行后续不同的操作 /* for (e <- it) { if(e.isInstanceOf[String]){ val str = e.asInstanceOf[String] // 可以针对字符串进行后续操作 } else if(e.isInstanceOf[Int]){ val i = e.asInstanceOf[Int] } } */ } }
-
元组也可以形成嵌套
scala// 元组嵌套 val t3 = (("Bob", 15), ("Amy", "female", 14), "Alex", (3, 5, "David")) println(t3) println(t3._1._1)
集合
转换
-
操作一
scalapackage com.fe.collection object CollectionDemo { def main(args: Array[String]): Unit = { // 数组 -> 其他 val arr = Array[Int](2, 3, 4, 2, 8, 8, 9) val arrToList = arr.toList println(arrToList) val arrToSet = arr.toSet println(arrToSet) // 列表 -> 其他 val list = List[Int](2, 3, 1, 4, 3, 2, 6) val listToArray = list.toArray println(listToArray.mkString(", ")) val listToSet = list.toSet println(listToSet) // 集合 -> 其他 val set = Set[Int](1, 2, 3, 4, 5) val setToArray = set.toArray println(setToArray.mkString(", ")) val setToList = set.toList println(setToList) } }
-
操作二
scalapackage com.fe.collection object CollectionDemo2 { def main(args: Array[String]): Unit = { val map = Map[String, Int]("Bob" -> 15, "Bruce" -> 16, "Bally" -> 17, "Cindy" -> 19, "Canto" -> 16) // Map -> Array val mapToArray = map.toArray println(mapToArray.mkString("\t")) // Map -> List val mapToList = map.toList println(mapToList) // Map -> Set val mapToSet = map.toSet println(mapToSet) // Array/List/Set如果需要转化为Map,要求其中的元素必须是对偶元组 val list = List[(Int, Int)]((1, 1), (2, 4), (3, 6)) println(list(1)._1) val listToMap = list.toMap println(listToMap) } }
常用函数
-
衍生子集合
scalapackage com.fe.collection object FunctionDemo { def main(args: Array[String]): Unit = { val list = List[Int](2, 1, 4, 7, 8, 5, 6) val set = Set[Int](2, 1, 4, 7, 8, 5, 6) // 获取第一个元素 println(list.head) println(set.head) // 获取最后一个元素 println(list.last) println(set.last) // 去除第一个元素以外的其他元素构成的子集合 println(list.tail) println(set.tail) // 去除最后一个元素以外的其他元素构成的子集合 println(list.init) println(set.init) // 翻转列表 println(list.reverse) // 从头部开始,向后获取指定个数的元素,构成子集合返回 println(list.take(3)) println(set.take(3)) // 从尾部开始,向前获取指定个数的元素,构成子集合返回 println(list.takeRight(3)) println(set.takeRight(3)) // 从头部开始,向后删除指定个数的元素,将剩余元素构成子集合返回 println(list.drop(3)) println(set.drop(3)) // 从尾部开始,向前删除指定个数的元素,将剩余元素构成子集合返回 println(list.dropRight(3)) println(set.dropRight(3)) // 从头开始,获取满足条件的元素,直到碰到不满足条件的元素结束,获取到的元素作为子集合返回 println(list.takeWhile(_ < 5)) // 从头开始,删除满足条件的元素,直到碰到不满足条件的元素结束,剩余的元素作为子集合返回 println(list.dropWhile(_ < 5)) } }
-
衍生集合
scalapackage com.fe.collection object FunctionDemo2 { def main(args: Array[String]): Unit = { val number = List[Int](1, 2, 3, 4, 5, 6, 7) val square = List[Int](1, 4, 9, 16, 25, 36, 49) // 拉链 // 将两个list合并成一个list,并且能够将元素来一一对应 // (1,1), (2,4), (3,9) ... // 拉链实际上是将对应位置上的元素合并成一个元组之后,放入一个list中返回 // 如果两个列表元素个数不一样,那么以短的长度来计算 // Seq、Set、Map也可以进行拉链操作!!! val zipList: List[(Int, Int)] = number.zip(square) println(zipList) // 需要将两个list合并成一个Map val zipMap = number.zip(square).toMap println(zipMap) val list = List[Int](2, 6, 4, 8, 7, 9, 1) val set = Set[Int](2, 6, 4, 8, 7, 9, 1) // 切分子集合 // 从指定下标开始,将列表切分为2个子列表,放入一个Tuple中返回 // val subLists:Tuple2[List[Int], List[Int]] = list.splitAt(4) val subLists: (List[Int], List[Int]) = list.splitAt(4) println(subLists) println(subLists._1(1)) val subSets: (Set[Int], Set[Int]) = set.splitAt(4) println(subSets) // 从集合的集合指定的起始下标开始,切到指定下标结束,不包含指定下标 println(list.slice(1, 4)) println(set.slice(1, 4)) // 滑动函数 - 将集合中固定个数元素进行组合,构成一个新的迭代器 // 0,1,2 1,2,3 2,3,4 ... list.sliding(3).foreach(println) set.sliding(3).foreach(println) // 指定步长的华东 // 0,1,2 2,3,4 4,5,6 ... list.sliding(3, 2).foreach(println) set.sliding(3, 2).foreach(println) } }
-
reduce
和fold
操作scalapackage com.fe.collection object FunctionDemo3 { def main(args: Array[String]): Unit = { val list = List[Int](1, 2, 3, 4, 5, 6, 7, 8, 9) // reduce:规约。将集合中的元素按照指定逻辑进行计算 // 需求:获取集合中所有的元素和 /* var sum = 0 for (e <- list) sum += e println(sum) */ // 求和:从左到右依次加上每一个元素 // 先计算前两个元素的和,获取结果,然后结果在加上第三个元素,再获取结果,加上下一个元素 // 集合中有5个元素e1~e5 // e1+e2 -> + e3 -> + e4 -> e5 // val sum = list.reduce((x, y) => x + y) val sum = list.reduce(_ + _) println(sum) // 需求:获取集合中所有的元素的积 println(list.reduce(_ * _)) // 等价于 println(list.reduceLeft(_ * _)) // 假设集合中有5个元素:e1~e5 // e4 - e5 -> r => e3 - r -> r => e2 - r -> r => e1 - r println(list.reduceRight(_ - _)) // fold的操作和reduce操作类似,fold可以指定初始值,在这个初始值的基础上来运算 // reduce就是没有初始值的fold操作 println(list.fold(10)(_ + _)) // 等价 println(list.foldLeft(10)(_ + _)) // 从右开始计算的 println(list.foldRight(10)(_ - _)) // 对集合元素进行集体运算的时候,如果没有初始值,就使用reduce;如果有初始值就使用fold } }
-
计算函数
scalapackage com.fe.collection object FunctionDemo4 { def main(args: Array[String]): Unit = { val list = List[Int](6, 4, 1, 5, 8, 9, 1, 3, 4) // 求和 // val sum = list.reduce(_ + _) val sum = list.sum println(sum) // 求积 // val product = list.reduce(_ * _) val product = list.product println(product) // 最大值 println(list.max) // 最小值 println(list.min) // 映射:记录的每一个字符出现的次数 // 需求:出现的最大次数对应的字符 val characters = List[(Char, Int)]('a' -> 5, 'c' -> 3, 'd' -> 6, 'e' -> 10, 'f' -> 7, 'i' -> 12, 'm' -> 8) // 如果集合中存储的是元组,那么默认按照元组的第一个元素来计算大小 // println(characters.max) println(characters.maxBy(t => t._2)) println(characters.maxBy(_._2)) // 获取出现次数最少的字符 println(characters.minBy(_._2)) // 按照字符的出现次数进行降序排序 println(characters.sortBy(_._2).reverse) } }
-
功能函数
scalapackage com.fe.collection object FunctionDemo5 { def main(args: Array[String]): Unit = { val names = List("Amy", "Bob", "Alex", "Hack", "David", "Peter", "Alice", "Bruce", "Henry", "Bill", "Bally") // filter:过滤 // 获取B开头的所有元素 // val filter = names.filter(n => n.startsWith("B")) val filter = names.filter(_.startsWith("B")) println(filter) // map:映射,将元素按照指定规则,转化为指定形式 // 将所有的元素转化为大写 // val map = names.map(e => e.toUpperCase) val map = names.map(_.toUpperCase) println(map) // groupBy:分组,按照指定规则,将元素分为分组 // 按照首字母,将元素分组 // val groupBy = names.groupBy(_.charAt(0)) // println("Amy"(0)) val groupBy: Map[Char, List[String]] = names.groupBy(_(0)) println(groupBy) // 需求:统计每一个字母开头有多少个名字 // 先分组,就是上面的分组操作 // 将映射由(Char -> List)转化为(Char -> Int)形式 val count = groupBy.map(t => (t._1, t._2.size)) println(count) // flatten:扁平化。将嵌套的所有的集合中的数据提取出来,形成一个大的集合 val list = List(List(1, 2, 3), List(4, 5), Set(6, 7, 8, 9)) println(list.flatten) // 将列表中的每一个单词拆分出来,形成新的列表 // String => List[String] val words = List("hello amy", "hadoop file system", "local system", "hi bob") // println(words.map(_.split(" ")).flatten) println(words.flatMap(_.split(" "))) } }
其他
泛型
- Scala中,通过
[]
来定义泛型 - 不同于Java的地方在于,Scala中的泛型,分为协变、逆变和不变三种形式
- 协变:
[+T]
。A继承了B,那么认为List[A]也继承了List[B] - 逆变:
[-T]
。A继承了B,那么认为List[B]继承了List[A] - 不变:
[T]
。A继承了B,List[A]和List[B]之间没有关联
- 协变:
- Scala同样存在泛型的上限和下限
[A <: B]
:泛型的上限为B[A >: B]
:泛型的下限为B