scala基础(三)

本文深入探讨Scala集合,包括Seq、Set、Map的不可变和可变版本,强调不可变集合的特点,以及数组、List、Set、Map、元组的使用。还介绍了各种集合操作函数,如排序、Fold和MergeMap,并通过WordCount案例展示了实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scala集合

1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable 特质。

2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两 个包 不可变集合:scala.collection.immutable 可变集合: scala.collection.mutable

3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而 不会对原对象进行修改。类似于 java 中的 String 对象

4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似 于 java 中 StringBuilder 对象

下面是尚硅谷里的两张关于可变集合与不可变集合的继承图。

 

1.数组

        1.1不可变数组

val ints = new Array[Int](10) //[T](size)
    //[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any

 ints.update(0,2)//修改!
    println(ints.apply(1)) // 和get()类似
 val ints3 :Array[Int] = ints :+5  //加在数组后面
//直接生成字符串用,分割
 println(ints.mkString(","))
//遍历有两种方式
 for (elem <- ints) {
      print(elem+" ") //Array的Index也是从0开始,且,数组Int的默认值是0
    }
def printx(elem:Int):Unit= {
      println(elem)
    }
    ints.foreach(printx)

        1.2可变数组ArrayBuffer

 val ab =  ArrayBuffer[Int](1,2,3,1)
    val aabb = new ArrayBuffer[Int]//()可加可不加
    ab.sizeHint(10)//指定一个暗示大小,节约空间,超了,系统根据该Hint值扩大数组(增大,复制)
    //ab.clear()
   // ab.remove(0,2)//(index,count)连续去除count次index的位置
    def printx(elem:Int): Unit ={
      println(elem)
    }
    ab.+= (3)//增加数据
    ab.append(2,2,2)
    ab.insert(3,8)
    ab(5)=213
    ab.foreach(printx)

1.3可变数组与不可变数组的转化

package Chap03JiHe

import scala.collection.mutable.ArrayBuffer

/*
arr1.toBuffer //不可变数组转可变数组
arr2.toArray //可变数组转不可变数组
(1)arr2.toArray 返回结果才是一个不可变数组,arr2 本身没有变化
(2)arr1.toBuffer 返回结果才是一个可变数组,arr1 本身没有变化

 */
object Test04ArrayChange {
  def main(args: Array[String]): Unit = {
    var arr1 = ArrayBuffer[Int](1,2,3,4)
    var arr2 =  Array[Int](3,4,5,76,34,1,23)

    val buffer = arr2.toBuffer
    val array  = arr1.toArray

    //arr1.clear() 说明没变

    arr1.foreach(printx)
    println()
    arr2.foreach(printx)
    println()
    buffer.foreach(printx)
    println()
    array.foreach(printx)

  }

}

1.4二(多)维数组

    val tarr = Array.ofDim[Int](3,5)//二维数组
    tarr(1)(2) = 1313
    //二维数组是由,数组加数组构成,即第一次返回值是Array 、第二次才是int
    for (elem <- tarr) {
      for (elem <- elem) {
        print(elem)
      }
      println()
    }

2.List

        2.1不可变List

        

    val list = List(1,2,3,4,5)
    val list5 = 1::2::3::4::Nil

    list5.foreach(printx)
    println()
    val list1 = 7::6::5::list
    list1.foreach(printx)
    println()
    var list2 = list.+:(5)  //在末尾加上5
    var list3 = 5::list     //在前面加上5
    list2.foreach(printx)    
    println()
    list3.foreach(printx)

    val list4 = list:::list3 //拼接
    println()
    list4.foreach(printx)

        2.2可变List- ListBuffer

    val lb = ListBuffer(1,2,3,45,5)

    lb.append(3,4,5)
    lb.insert(3,4444)

    lb.foreach(printx)

    lb(2) = 232332
    lb.update(5,222222)

    lb.-=(1)
    //lb.-(3)
    lb.remove(2,5)
    println()
    lb.foreach(printx)

     3.Set

        3.1不可变Set

package Chap03JiHe
/*
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用
scala.collection.mutable.Set 包
(1)Set 默认是不可变集合,数据无序
(2)数据不可重复
(3)遍历集合
 */
object Test08SetInit {
  def main(args: Array[String]): Unit = {
    val set = Set(1,2,3,4,5,6)
    val set1 = Set(1,2,3,4,5,6,3)
    for(x<-set1){
      println(x)
    }
  }
}

        3.2可变Set

package Chap03JiHe

import scala.collection.mutable

object Test09MutableSet {
  def main(args: Array[String]): Unit = {
    val mset = mutable.Set(1,2,3,4,5,6)

    mset += 8

    //(4)向集合中添加元素,返回一个新的 Set
    val ints = mset.+(9)
    println(ints)
    println("set2=" + mset)
    mset -= (5)

    mset.foreach(println)
    println(mset.mkString(","))

  }
}

 4.Map

        4.1不可变Map

package Chap03JiHe

import scala.collection.mutable

/*
Scala 中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对(key-value)映射

 */
object Test10Map {
  def main(args: Array[String]): Unit = {
    val map = Map( "a"->1, "b"->2, "c"->3 )
    //map.keys直接拿到所有的keys
    for (elem <- map.keys){
      println(elem+"="+map.get(elem))//直接使用get会返回Option类型
      println(elem+"="+map.get(elem).get)
    }

    println(map.get("d").getOrElse(0))
    //拿到的是一个Array[String]?  //通过后面的学习我们知道,这就是一个元组
    println(map("a")) //类似数组一样也可以访问  底层hashcode寻址。

    map.foreach((a) => {println(a)})
    map.foreach((a) => {println(a._1+"-"+a._2)})

    val mmap = mutable.Map( "a"->1, "b"->2, "c"->3 )
    val mmap2 = mutable.Map( "aaaa"->1, "b"->233, "adasd"->3 )
    //(3)向集合增加数据
    mmap+=("d"->4)
    mmap+=(("e",333)) //两个括号
    // 将数值 4 添加到集合,并把集合中原值 1 返回
    val maybeInt: Option[Int] = mmap.put("a", 4)
    println(maybeInt.getOrElse(0))
    //(4)删除数据
    //map.remove(key)
    mmap-=("b", "c")
    //(5)修改数据
    mmap.update("d",5)
    mmap("d") = 5
    mmap.foreach((kv)=>{println(kv)})
    mmap.foreach((kv)=>{println(kv._1+"-"+kv._2)})

    //合并两个可变map
    mmap ++= mmap2  //直接添加,若重复 覆盖。 后续在训练wordcount时,不会使用这样的方式
    println(mmap)
  }

}

        4.2可变Map

package Chap03JiHe

import scala.collection.mutable

object MutableMap {
  def main(args: Array[String]): Unit = {
    val map = mutable.Map( "a"->1, "b"->2, "c"->3 )
    //(3)向集合增加数据
    map+=("d"->4)
    // 将数值 4 添加到集合,并把集合中原值 1 返回
    val maybeInt: Option[Int] = map.put("a", 4)
    println(maybeInt.getOrElse(0))
    //(4)删除数据
    map.-=("b", "c")
    //(5)修改数据
    map.update("d",5)
    map("d") = 5
    map.foreach((kv)=>{println(kv)})
    map.foreach((kv)=>{println(kv._1+"-"+kv._2)})
  }

}

5.元组

package Chap03JiHe
/*
直接看成一个复杂的键值对类型也可。
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就
是将多个无关的数据封装为一个整体,称为元组。
注意:元组中最大只能有 22 个元素。

 */
object Test11YuanZu {
  def main(args: Array[String]): Unit = {
    var tuple =(40,"bobo",true)

    println(tuple._2)
    println(tuple._1)
    println(tuple._3)

    println(tuple.productElement(2))
    for(elem <- tuple.productIterator){
      println(elem)
    }
    //(3)Map 中的键值对其实就是元组,只不过元组的元素个数为 2,称之为对偶

    val map = Map("a"->1, "b"->2, "c"->3)
    val map1 = Map(("a",1), ("b",2), ("c",3))
    map.foreach(tuple=>{println(tuple._1 + "=" + tuple._2)})

  }
}

6.对集合操作的函数

        6.1基础函数

package Chap03JiHe

object Test12BasicFuction {
  def main(args: Array[String]): Unit = {
    val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
    //(1)获取集合长度
    println(list.length)
    //(2)获取集合大小,等同于 length
    println(list.size)
    //(3)循环遍历
    list.foreach(println)
    //(4)迭代器
    for (elem <- list.iterator) {
      println(elem)
    }
    //(5)生成字符串
    println(list.mkString(","))
    //(6)是否包含
    println(list.contains(3))
package Chap03JiHe

object Test13YanSheng {
  def main(args: Array[String]): Unit = {
    val list1 = List[Int](1,2,3,4,5,6,7)
    val list2 = List[Int](1,2,3,4,5,6,7,8,9,10)

    println(list1.head)
    //(2)获取集合的尾(不是头的就是尾)故尾巴是 2,3,4,5,6,7
    println(list1.tail)
    println(list1.tails)//返回的是迭代器
    println(list1.init)

    println(list1.reverse)
    println(list1.take(3))
    println(list1.takeRight(3))

    println(list1.drop(3))
    println(list1.dropRight(3))

    //(8)并集
    println(list1.union(list2))
    //(9)交集
    println(list1.intersect(list2))
    //(10)差集
    println(list1.diff(list2))

    //(11)拉链 注:如果两个集合的元素个数不相等,那么会将同等数量的数据进
   // 行拉链,多余的数据省略不用
    println(list1.zip(list2))
    //滑窗?
    list1.sliding(2, 5).foreach(println)
  }
}

  }
}

 6.2排序

package Chap03JiHe

object Test14ListSort {
  def main(args: Array[String]): Unit = {
    val list: List[Int] = List(1, 5, -3, 4, 2, -7, 6)
    //(1)求和
    println(list.sum)
    //(2)求乘积
    println(list.product)
    //(3)最大值
    println(list.max)
    //(4)最小值
    println(list.min)
    //(5)排序
    // (5.1)按照元素大小排序
    println(list.sortBy(x => x))
    // (5.2)按照元素的绝对值大小排序
    println(list.sortBy(x => x.abs))
    // (5.3)按元素大小升序排序
    println(list.sortWith((x, y) => x < y))
    // (5.4)按元素大小降序排序
    println(list.sortWith((x, y) => x > y))
    /*
    (1)sorted
对一个集合进行自然排序,通过传递隐式的 Ordering
(2)sortBy
对一个属性或多个属性进行排序,通过它的类型。
(3)sortWith
基于函数的排序,通过一个 comparator 函数,实现自定义排序的逻辑。
     */
  }


}

6.3复杂函数,大量用于MR

package Chap03JiHe
/*
(1)过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化
(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作
集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group)
按照指定的规则对集合的元素进行分组
(6)简化(归约)
 (7)折叠
 */
object Test15HarderFuc {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val nestedList = List(List(1, 2, 3), List(4,5, 6), List(7, 8, 9))
    val wordList = List("hello world", "hello atguigu", "hello scala")
    //(1)过滤   filter 返回boolean  处理map
    println(list.filter(x => x % 2 == 0))
    //(2)转化/映射
    println(list.map(x => x + 1))
    println(list.map( x => x * 2))
    //(3)扁平化
    println(nestedList.flatten)
    //(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作
    val value = wordList.map( _.split(" ") )
    println(value)
    val flatten = value.flatten
    println(flatten)


    println(wordList.flatMap(x => x.split(" ")))
    //(5)分组
    println(list.groupBy(x => x % 2))
  }
}
package Chap03JiHe

object Test16HarderFuc2Reduce {//mr里 reduce就是归并起来。
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4)

    //1.   (A1,A1) => A1
    println(list.reduce(_+_)) //底层调用的是reduceleft
    print("=======================")

    val list2 = List(3,4,5,8,10)
    println(list2.reduce(_-_)) //3-4-5-8-10 = -24
    println(list2.reduceRight(_-_)) //这句话=> 3-(4-(5-(8-10)))  递归执行reduceleft
    //底层是递归
    /*  与视频中的源码不同,重新改了写法,看最后一句即可。
    def reduceRight[B >: A](op: (A, B) => B): B = {
    val it = iterator
    if (it.isEmpty)
      throw new UnsupportedOperationException("empty.reduceRight")

    reversed.reduceLeft[B]((x, y) => op(y, x))
  }
     */

  }
}

6.4Fold

package Chap03JiHe

import scala.math.Fractional.Implicits.infixFractionalOps

object Test17Fold {
  /*
  新的源码比之前的好理解,直接不停的调用聚合。即跟着迭代器,每迭代一个进行一次计算。
  给如的z 是一个初始值。
  def foldLeft[B](z: B)(op: (B, A) => B): B = {
    var result = z
    val it = iterator
    while (it.hasNext) {
      result = op(result, it.next())
    }
    result
  }
   */
  def main(args: Array[String]): Unit = {
    val list = List(3,4,5,8,10)
    println(list.fold(10)(_*_))

    println(list.foldLeft(10)(_-_))
    println(list.foldRight(10)(_-_))  //=> 3-(4-(5-(8-(10-10)

    /*      override def foldRight[B](z: B)(op: (A, B) => B): B =
            reverse.foldLeft(z)((right, left) => op(left, right))
            与ReduceRight类似 无限递归
     */
  }
}

6.5MergeMap

package Chap03JiHe

import scala.collection.mutable

object Test18Merge_map {
  def main(args: Array[String]): Unit = {
    val map1 =Map("a" -> 1 ,"b" ->3,"c"->22)
    val map2 =mutable.Map("a" -> 23 ,"b" ->13,"c"->2,"d"->11,"e"->3)
    //类似wordcount里map好了我们需要reduce
    //def foldLeft[B](z: B)(op: (B, A) => B): B =  返回值是B 即一个map  A是kv对
    val map3 = map1.foldLeft(map2)(
      (mergedMap,kv) => {
        val key = kv._1
        val value = kv._2
       // mergedMap(key) = mergedMap.getOrElse(key, 0)+value
        mergedMap.put(key,mergedMap.getOrElse(key,0)+value)
        println(mergedMap)//
        mergedMap
      }
    )
    println(map3)
  }
  /*
  HashMap(a -> 24, b -> 13, c -> 2, d -> 11, e -> 3)
HashMap(a -> 24, b -> 16, c -> 2, d -> 11, e -> 3)
HashMap(a -> 24, b -> 16, c -> 24, d -> 11, e -> 3)
HashMap(a -> 24, b -> 16, c -> 24, d -> 11, e -> 3)
说明此时的mergdmap初始值是map2 ,然后map1进来  加进去
所以此时map1是可以是死map  而map2必须是mutable
   */

}

7.WordCount案例演示

package Chap03JiHe

object Test17_ComWordCount {
  def main(args: Array[String]): Unit = {
    val stringlist: List[String] =List("hello","hello world","hello scala",
      "hello spark from scala","hello flink from scala")
    //切分
//    val wordList1: List[Array[String]] = stringlist.map(_.split(" "))
//    println(wordList1)//五个Array[String]
//    //初始值应当是一个空的元
//    val wordList2 = wordList1.flatten
//    println(wordList2)
    val wordlist: List[String] = stringlist.flatMap(_.split(" "))
    //分组操作
    val groupMap: Map[String, List[String]] = wordlist.groupBy(word => word)
    println(groupMap)
    //分组之后对list取长度
    val wordcount: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))
    println(wordcount)
    //转换成list 排序取前三
    val sortList: List[(String, Int)] = wordcount.toList
      .sortWith(_._2 > _._2)
      .take(3)
    println(sortList)
  }
}

WordCount高级案例

package Chap03JiHe

import scala.collection.MapView

object Test18CompleWordCount {
  def main(args: Array[String]): Unit = {
    //此时相当于maptask已经返回了几个预处理过的计算  我们现在需要对其进行一个reduce合并。
    val tuplelist: List[(String, Int)] = List(
      ("hello", 3),
      ("hello world", 4),
      ("hello scala", 2),
      ("hello spark from scala", 6),
      ("hello flink from scala", 9)
    )
    //直接展开,然后再按照key合并最后排序输出
    val newStringList: List[String] = tuplelist.map(
      kv => {
        (kv._1.trim + " ") * kv._2
      }
    )
    println(newStringList)
    /*val flattenMap: Map[String, List[String]] = newStringList.flatten(_.split(" ")).groupBy(k => k)
    println(flattenMap)
    val stringIntMap: Map[String, Int] = flattenMap.map(
      kv => {
        (kv._1, kv._2.length)
      }
    )
    println(stringIntMap)
    val resultList: List[(String, Int)] = stringIntMap.toList.sortWith(_._2 > _._2).take(3)
    println(resultList)*/
    val res: List[(String, Int)] = newStringList
      .flatMap(_.split(" "))
      .groupBy(k => k)
      .map(kv => (kv._1, kv._2.length))
      .toList
      .sortWith(_._2 > _._2)
      .take(3)
    //过于复杂了,
    println(res)

    //思路2:直接基于预统计的结果进行转换
    val preCountList: List[(String, Int)] = tuplelist.flatMap(
      kv => {
        val strings: Array[String] = kv._1.split(" ")
        strings.map(string => (string, kv._2)) //返回的成了Array[(String,Int)] 就已经可以了因为会帮你扁平化
      }
    )
    println(preCountList)
    //对元祖进行聚合
    val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy(kv => kv._1)
    //把value值叠加
    val countMap: MapView[String, Int] = preCountMap.mapValues(list => list.map(_._2).sum)
    println(countMap.toMap.toList.sortWith(_._2 > _._2))
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值