Scala详解(6)

Scala

集合

字符串

  1. Scala中字符串同样分为可变字符串和不可变字符串,不可变字符串使用String来定义,可变字符串使用的是StringBuilder来定义

    复制代码
    package com.fesco.string
    ​
    object StringDemo {
    ​
      def main(args: Array[String]): Unit = {
    ​
        // 可变字符串
        // Scala中既然将字符串看作是集合中的成员,那么字符串其实就是字符的集合
        val str: StringBuilder = new StringBuilder("abc")
        str += 'a'
        println(str)
        // 产生一个新的字符串
        val r1 = str.+("abc")
        println(str)
        println(r1)
        // 将结果转化为一个ArrayBuffer返回
        val r2 = str.:+('c')
        println(str)
        println(r2)
        str.++=("abc")
        println(str)
    ​
      }
    ​
    }

序列(Seq)

  1. 数组、列表、字符串都属于序列的子类

  2. 序列分为可变序列和不可变序列。不可变序列分为两大类:

    1. IndexedSeq:索引序列,支持通过索引来快速定位元素的位置,包含StringArrayVectorRange

    2. LinearSeq:线性序列,除了支持索引的功能以外,还有头和尾的概念,包含ListQueueStack

  3. a to b还是a until b返回就是一个Range对象

    复制代码
    // a to b 本质上就是返回了一个Range集合
    // for (i <- 1 to 10) println(i)
    // 实际上底层是
    val range = Range(1, 10)
    for (i <- range) println(i)
  4. Seq本身是一个特质,无法直接构建对象,同时伴生对象中也没有提供用于获取Seq对象的方法

  5. Seq的基本操作

    1. 索引和长度

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo {
      ​
        def main(args: Array[String]): Unit = {
      ​
          val list = List[Int](2, 4, 1, 5, 7)
          val arr = Array[Int](3, 5, 4, 1, 8, 0)
      ​
          // 通过指定下标来获取元素
          println(list(2))
          // 获取长度/元素个数
          println(list.length)
          println(list.size)
          println(arr.size)
          // 索引范围
          // 0 ~ list.length-1
          val indices: Range = list.indices
          println(indices)
          // 遍历序列
          for (i <- list.indices) println(list(i))
          // isDefinedAt:判断下标是否在indices范围内
          println(list.isDefinedAt(3))
          // 等价于
          println(3 < list.length && 3 > 0)
          // a lengthCompare b:a的长度大于b,返回1;a的长度小于b返回-1;a的长度等于b,返回0
          println(list.lengthCompare(arr))
          println(list.length == arr.length)
      ​
        }
      ​
      }
    2. 索引搜索

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo2 {
      ​
        def main(args: Array[String]): Unit = {
      ​
          val list = List[Int](3, 2, 1, 5, 7, 5, 4, 9, 8)
      ​
          // indexOf:获取指定元素在序列中第一次出现的下标
          println(list.indexOf(5))
          // lastIndexOf:获取指定元素在序列中最后一次出现的下标
          println(list.lastIndexOf(5))
          // indexOfSlice:子序列在序列中第一次出现的下标
          val sub = List[Int](4, 9)
          println(list.indexOfSlice(sub))
          // lastIndexOfSlice:子序列在序列中最后一次出现的下标
          println(list.lastIndexOfSlice(sub))
          // indexWhere:指定条件,获取满足条件的第一个元素出现的下标
          // 在序列中,大于5的元素第一次出现的下标
          // 默认从第0为开始寻找
          // list.indexWhere(x => x > 5)
          println(list.indexWhere(_ > 5))
          // 从指定下标开始向后寻找
          println(list.indexWhere(_ > 5, 5))
          // 根据开头过滤
          val languages = List[String]("Java", "Python", "Perl", "Scala", "Ruby", "Kotlin", "Pascal")
          println(languages.indexWhere(_.startsWith("P")))
          // prefixLength:已过时,推荐使用segmentLength。不满足条件的元素,第一次出现的下标
          // println(list.prefixLength(_ > 5))
          println(list.segmentLength(_ > 5))
      ​
        }
      ​
      }
    3. 增加/更新

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo3 {
      ​
        def main(args: Array[String]): Unit = {
      ​
          val list = List[Int](3, 2, 1, 5, 7, 9, 8)
      ​
          // 尾部追加
          val r1 = list :+ 4
          println(r1)
          // 头部追加
          val r2 = 3 +: list
          println(r2)
          // 扩充序列,将序列的长度扩为10
          val r3 = list.padTo(10, 0)
          println(r3)
          // 更新数据
          val r4 = list.updated(2, 4)
          println(r4)
          // list(2) = 4只支持可变序列
          // patch(from, 子序列, 替换长度):从序列的第from下标开始,替换指定个数的元素,替换为子序列中的元素
          val v = List[Int](2, 4, 6)
          val r5 = list.patch(3, v, 3)
          println(r5)
      ​
      ​
        }
      ​
      }
    4. 排序

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo4 {
      ​
        def main(args: Array[String]): Unit = {
      ​
          // 对元素进行自然排序
          val list = List[Int](3, 2, 1, 5, 7, 9, 8)
          val r1 = list.sorted
          println(r1)
      ​
          val s1 = new Student("Amy", 15, 92)
          val s2 = new Student("Bob", 13, 85)
          val s3 = new Student("Tom", 14, 78)
          val s4 = new Student("Sam", 16, 91)
          val s5 = new Student("Tony", 17, 65)
          val s6 = new Student("Eden", 16, 72)
          val s7 = new Student("Hack", 15, 78)
          val students = List[Student](s1, s2, s3, s4, s5, s6, s7)
          // 按照学生姓名排序
          // 根据元素中的某一个属性来排序
          // students.sortBy(s => s.name)
          val namedStudents = students.sortBy(_.name)
          println(namedStudents)
          //  规则:按照分数进行降序排序,如果分数相同,则按照年龄升序
          println("=" * 50)
          val r2 = students.sortWith((s1, s2) => if (s1.score != s2.score) s1.score > s2.score else s1.age < s2.age)
          println(r2)
      ​
      ​
        }
      ​
      }
      ​
      class Student(val name: String, val age: Int, val score: Int) {
        override def toString: String = s"{name:$name, age:$age, score:$score}\n"
      }
    5. 判断

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo5 {
      ​
        def main(args: Array[String]): Unit = {
      ​
          val list = List[Int](1, 2, 3, 4, 5)
          val sub = List[Int](1, 2)
      ​
          // startsWith
          println(list.startsWith(sub))
          // endsWith
          println(list.endsWith(sub))
          // 判断是否包含了指定元素
          println(list.contains(3))
          // 判断是否包含指定子列
          println(list.containsSlice(sub))
      ​
          val number = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
          val twice = 2 :: 4 :: 6 :: 8 :: 10 :: Nil
          // 判断twice中的元素是否是number中对应位置上元素的2倍
          // number.corresponds(twice)((x, y) => x * 2 == y)
          println(number.corresponds(twice)(_ * 2 == _))
      ​
        }
      ​
      }
    6. 多序列操作

      复制代码
      package com.fesco.seq
      ​
      object SeqDemo6 {
      ​
        def main(args: Array[String]): Unit = {
      ​
          val list1 = List[Int](2, 4, 6, 8, 10)
          val list2 = List[Int](1, 2, 4, 8, 16, 32)
      ​
          // 并集 - a ∪ b,将a和b的数据放到一起
          val r1 = list1 ++: list2
          println(r1)
          val r2 = list1 :++ list2
          println(r2)
          val r3 = list1 concat list2
          println(r3)
          val r4 = list1 ::: list2
          println(r4)
          val r5 = list1 union list2
          println(r5)
          // 交集 - a ∩ b,获取a和b都有的数据
          val r6 = list1 intersect list2
          println(r6)
          // 差集 - a有b没有的
          val r7 = list1 diff list2
          println(r7)
          // 去重
          val r8 = r1.distinct
          println(r8)
      ​
        }
      ​
      }

集合(Set)

不可变集合(Set)
  1. 注意:在Scala中,无论是可变集合还是不可变集合,都是使用Set来定义,区别是可变集合是scala.collection.mutable.Set,不可变集合是scala.collection.immutable.Set

  2. 定义格式

    复制代码
    package com.fesco.set
    ​
    object SetDemo {
    ​
      def main(args: Array[String]): Unit = {
    ​
        // 不可变集合Set本身是一个特质,就意味着无法直接创建对象
        // 方式一:创建空集合
        val set: Set[String] = Set.empty[String]
        println(set)
        // 方式二:
        // 无序不可重复
        val set2: Set[Int] = Set[Int](2, 4, 6, 8)
        println(set2)
    ​
      }
    ​
    }
  3. 基本操作

    复制代码
    package com.fesco.set
    ​
    object SetDemo2 {
    ​
      def main(args: Array[String]): Unit = {
    ​
        val set = Set[Int](1, 3, 5, 7, 9)
    ​
        // 添加元素
        val r1 = set + 2
        println(r1)
        // 删除元素
        val r2 = set - 3
        println(r2)
        // 并集
        val set2 = Set[Int](2, 4, 6, 8)
        val r3 = set ++ set2
        println(r3)
        val r4 = set union set2
        println(r4)
        val r5 = set concat set2
        println(r5)
        val r10 = set | set2
        println(r10)
        // 差集
        val set3 = Set[Int](1, 2, 3, 4)
        val r6 = set -- set3
        println(r6)
        val r7 = set diff set3
        println(r7)
        val r11 = set &~ set3
        println(r11)
        // 交集
        val r8 = set intersect set3
        println(r8)
        val r9 = set & set3
        println(r9)
        // 遍历
        set.foreach(println)
    ​
      }
    ​
    }
可变集合(Set)
  1. 可变集合依然使用Set来定义

    复制代码
    val set = mutable.Set[Int]()
  2. 基本操作

    复制代码
    package com.fesco.set
    ​
    import scala.collection.mutable
    ​
    object SetDemo3 {
    ​
      def main(args: Array[String]): Unit = {
    ​
        // 创建可变集合对象
        val set = mutable.Set[Int]()
        println(set)
        // 添加元素
        set += 7
        println(set)
        set add 8
        println(set)
        // 删除元素
        set -= 7
        println(set)
        set remove 8
        println(set)
    ​
        // 合并集合
        val set1 = mutable.Set[Int](5, 5, 4, 7, 8, 9)
        val set2 = mutable.Set[Int](2, 4, 6, 8, 10)
        set1 ++= set2
        println(set1)
        // 差集
        val set3 = mutable.Set[Int](5, 4, 7, 8, 9)
        val set4 = mutable.Set[Int](2, 4, 6, 8, 10)
        set3 --= set4
        println(set3)
    ​
      }
    ​
    }

映射(Map)

不可变映射
  1. 注意:Scala中,可变映射和不可变映射都是通过Map来定义。默认使用的是不可变映射

  2. Map本身是一个特质,无法直接创建对象,所以使用的是伴生对象

    复制代码
    package com.fesco.map
    ​
    object MapDemo {
    ​
      def main(args: Array[String]): Unit = {
    ​
        // Map存储的是键值对,所以泛型需要指定2个
        // 定义的时候就需要给定键值对
        // 方式一
        val map = Map[String, Int]("Amy" -> 85, "Bob" -> 74, "Cindy" -> 63, "David" -> 59, "Evan" -> 60)
        println(map)
        // 方式二
        val map2 = Map[String, Int](("Frank", 15), ("Grace", 24), ("Henry", 36), ("Iran", 44))
        println(map2)
    ​
      }
    ​
    }
  3. 基本操作

    复制代码
    package com.fesco.map
    ​
    object MapDemo2 {
    ​
      def main(args: Array[String]): Unit = {
    ​
        val map = Map[String, Int]("Jack" -> 85, "Kathy" -> 79, "Lily" -> 64, "Mark" -> 58, "Nelson" -> 84)
    ​
        // 添加键值对
        val r1 = map + ("Odersky" -> 75)
        println(r1)
        val r2 = map + (("Peter", 74))
        println(r2)
        // 如果添加的键值对的键已经存在,那么对应的值来进行替换
        val r3 = map + ("Lily" -> 81)
        println(r3)
        // 移除指定的键对应的键值对
        val r4 = map - "Nelson"
        println(r4)
        // 获取指定键对应的值
        // 为了防止空指针异常,将get函数的返回值封装成了Option类型
        // 如果有实际值,那么可以从Option中获取到实际值
        // 如果没有实际值,那么会从Option获取到None
        val r5:Option[Int] = map get "Mark"
        val r6:Option[Int] = map get "Rose"
        // println(if(!r5.isEmpty) r5.get else r5)
        println(if(r5.isDefined) r5.get else r5)
        // println(if(!r6.isEmpty) r6.get else r6)
        println(if(r6.isDefined) r6.get else r6)
        // 获取指定键对应的值,如果键存在,那么返回实际值;如果键不存在,返回指定的值
        val r7 = map.getOrElse("Thomas", 0)
        println(r7)
    ​
      }
    ​
    }
可变映射
  1. 可变映射也是通过Map来定义

  2. 基本操作

    复制代码
    package com.fesco.map
    ​
    import scala.collection.mutable
    ​
    object MapDemo3 {
    ​
      def main(args: Array[String]): Unit = {
    ​
        val map = mutable.Map[String, Int]()
    ​
        // 添加元素
        map.put("Adair", 84)
        map.put("Bruce", 58)
        map.put("Bruce", 67)
        println(map)
        map += ("Cindy" -> 72)
        map += (("Danny", 72))
        println(map)
        // 修改指定的键对应的值
        map.update("Cindy", 85)
        map("Adair") = 96
        println(map)
        // 获取指定的键对应的值
        // get函数将结果封装成Option[Some]对象
        // Option[Int] => Option[Some]
        val r1: Option[Int] = map.get("Bruce")
        println(r1)
        val r2: Int = map("Bruce")
        println(r2)
        val r3 = map.getOrElse("Fed", 0)
        println(r3)
        // 删除指定键对应的值
        map remove "Bruce"
        map -= "Adair"
        println(map)
    ​
      }
    ​
    }
遍历映射
  1. 键的遍历:遍历所有的键,通过键来获取值

    复制代码
    package com.fesco.map
    ​
    object MapDemo4 {
    ​
      def main(args: Array[String]): Unit = {
    ​
        val map = Map[String, Int]("Peter" -> 15, "Tony" -> 17, "Simon" -> 16, "Kohn" -> 18, "Lucy" -> 20, "Vincent" -> 21, "William" -> 20)
    ​
        // 键的遍历
        // 方式一:keySet,将所有的键放入一个Set中返回
        val keySet: Set[String] = map.keySet
        for (key <- keySet) println(s"key:$key, value:${map(key)}")
        // 方式二:keys,将所有的键放入一个Iterable中返回
        println("=" * 100)
        val keys: Iterable[String] = map.keys
        for (key <- keys) println(s"key:$key, value:${map(key)}")
        // 方式三:keysIterator,将所有的键放入一个Iterator中返回
        println("=" * 100)
        val keysIterator: Iterator[String] = map.keysIterator
        for (key <- keysIterator) println(s"key:$key, value:${map(key)}")
    ​
      }
    ​
    }
  2. 获取所有的值

    复制代码
    package com.fesco.map
    
    object MapDemo5 {
    
      def main(args: Array[String]): Unit = {
    
        val map = Map[String, Int]("Peter" -> 15, "Tony" -> 17, "Simon" -> 16, "Kohn" -> 18, "Lucy" -> 20, "Vincent" -> 21, "William" -> 20)
    
        // 获取所有的值
        // 方式一
        val values: Iterable[Int] = map.values
        for (value <- values) println(value)
        // 方式二
        println("=" * 50)
        val valuesIterator: Iterator[Int] = map.valuesIterator
        for (elem <- valuesIterator) println(elem)
    
      }
    
    }
  3. 遍历映射

    复制代码
    package com.fesco.map
    
    object MapDemo6 {
    
      def main(args: Array[String]): Unit = {
    
        val map = Map[String, Int]("Peter" -> 16, "Tony" -> 17, "Simon" -> 16, "Kohn" -> 18, "Lucy" -> 20, "Vincent" -> 21, "William" -> 20)
    
        // 方式一:iterator,将键值对放入一个Iterator中返回
        val it: Iterator[(String, Int)] = map.iterator
        for (t <- it) println(s"key:${t._1}, value:${t._2}")
        // 方式二:直接使用增强for循环,本质上就是一个迭代过程
        println("=" * 50)
        for (t <- map) println(s"key:${t._1}, value:${t._2}")
        // 方式三:foreach函数
        println("=" * 50)
        map.foreach(t => println(s"key:${t._1}, value:${t._2}"))
    
    
      }
    
    }
  4. 映射中的键值对实际上就是Tuple2,Tuple2又称之为对偶元组。因此,在Scala中,Map实际上就是一个存储了多个Tuple2的数组

相关推荐
jk_10117 分钟前
MATLAB中decomposition函数用法
开发语言·算法·matlab
weixin_4640780717 分钟前
C#串口温度读取
开发语言·c#
无敌の星仔20 分钟前
一个月学会Java 第2天 认识类与对象
java·开发语言
豆豆42 分钟前
为什么用PageAdmin CMS建设网站?
服务器·开发语言·前端·php·软件构建
落落落sss1 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
简单.is.good2 小时前
【测试】接口测试与接口自动化
开发语言·python
bubble小拾2 小时前
ElasticSearch高级功能详解与读写性能调优
大数据·elasticsearch·搜索引擎
Yvemil72 小时前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的2 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
ZOHO项目管理软件2 小时前
EDM平台大比拼 用户体验与营销效果双重测评
大数据