• 大数据——Scala 元组


    Scala

    元组(Tuple)

    1. 元组(Tuple)本身是一个用于存储1到多个元素的容器,需要注意的是,元组不是集合!!!Scala中所有的集合都在scala.collection包,Tuple是scala包下,但是集合操作中很多时候需要使用到元组

    2. 如果元素类型一致且元素有序可重复,可以使用序列(Seq);如果元素类型一致且元素无序不可重复,可以使用集合(Set);如果元素是键值对形式,可以使用映射(Map);如果元素类型不一致,那么使用元组Tuple

    3. 需要注意的是,Scala中提供了Tuple1~Tuple22,即元组中最多能够存储22个元素

    4. 之前学习的Map中存储的就是Tuple2,即Map(tuple2, tuple2, ...)。Tuple2又称之为对偶元组

    5. 元组定义格式

      package 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)
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
    6. 遍历元组

      package 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]
            }
          }
           */
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
    7. 元组也可以形成嵌套

      // 元组嵌套
      val t3 = (("Bob", 15), ("Amy", "female", 14), "Alex", (3, 5, "David"))
      println(t3)
      println(t3._1._1)
      
      • 1
      • 2
      • 3
      • 4

    集合

    转换

    1. 操作一

      package 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)
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    2. 操作二

      package 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)
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

    常用函数

    1. 衍生子集合

      package 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))
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
    2. 衍生集合

      package 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)
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
    3. reducefold操作

      package 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
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
    4. 计算函数

      package 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)
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
    5. 功能函数

      package 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(" ")))
      
        }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40

    其他

    泛型

    1. Scala中,通过[]来定义泛型
    2. 不同于Java的地方在于,Scala中的泛型,分为协变、逆变和不变三种形式
      1. 协变:[+T]。A继承了B,那么认为List[A]也继承了List[B]
      2. 逆变:[-T]。A继承了B,那么认为List[B]继承了List[A]
      3. 不变:[T]。A继承了B,List[A]和List[B]之间没有关联
    3. Scala同样存在泛型的上限和下限
      1. [A <: B]:泛型的上限为B
      2. [A >: B]:泛型的下限为B
  • 相关阅读:
    精通python需要学习那些课程?
    Java中有scanf吗?
    论文翻译:2018_Source localization using deep neural networks in a shallow water environment
    Simulink|用于光伏系统最大功率点跟踪(MPPT)的极值寻道控制(ESC)【采用极值寻道控制算法求解非线性函数的最大/最小点】
    verilog学习笔记(1)module实例化2
    博弈论算法的实现2
    康迈斯多通路基因抗衰老之九:PQQ PRO线粒体能量
    ch552g下载时遇到的可能问题
    同城跑腿微信小程序源码系统完整搭建教程
    基于改进遗传算法的卡车和两架无人机旅行推销员问题(D2TSP)(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/weixin_51401546/article/details/137930395