大数据开发语言Scala(二)——集合的基本属性和常用操作

本文详细介绍了Scala中的集合框架,包括不可变与可变集合的区别,如Seq、Set、Map以及List的特性与操作。讨论了数组的创建、访问、遍历和转换,不可变与可变数组的差异。此外,还涵盖了List的不可变性以及可变列表ListBuffer的操作。Set的不可变与可变实现,以及Map的使用,包括元组的概念和操作。最后,文章提到了并行集合par,用于多核环境的并行计算。
摘要由CSDN通过智能技术生成

一、集合简介

1.1 集合简介

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

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

不可变集合:scala.collection.immutable

可变集合: scala.collection.mutable

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

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

建议:在操作集合的时候,不可变用符号,可变用方法

1.2 不可变集合继承图:

1.3 可变集合继承图:

二、数组

2.1 不可变数组

1)定义数组

方式一:val arr1 = new Array[Int](10)
1. new是关键字
2. [Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any
3. (10)表示数组的大小,确定后就不可以变化

方式二:val arr2 = Array(1,2,3,4,5);
1. 在定义数组时,直接赋初始值
object ImmutableArray {
  def main(args: Array[String]): Unit = {
    // 1. 创建数组
    val arr1 = new Array[Int](5);
    // 另一种创建方式
    val arr2 = Array(1,2,3,4,5);

    // 2. 访问元素
    arr1(0) = 12
    arr1(1) = 23
    println(arr1(0))    // 12
    println(arr1(1))    // 23
    println(arr1(2))    // 0
  }

    // 3. 数组的遍历
    // 1) 普通for循环
    for(i <- 0 until arr1.length){
      println(arr1(i))
    }
    for(i <- arr1.indices) println(arr1(i))
    // 2) 遍历所有元素,增强for循环
    for(elem <- arr2)println(elem)
    // 3) 迭代器
    val iter = arr1.iterator
    while (iter.hasNext) println(iter.next())
    // 4) 调用foreach方法
    arr1.foreach( println )
    // 5) 调用函数
    println(arr1.mkString("-"))

    // 4. 不可变数组添加元素
    val arr11 = arr1:+10
    println(arr11.mkString("-"))    // 数字加在后面:12-23-0-0-0-10
    val arr12 = 11+:arr1
    println(arr12.mkString("-"))    // 数字加在前面:11-12-23-0-0-0
}

2.2 可变数组

object ArrayBuffer {
  def main(args: Array[String]): Unit = {
    // 1. 创建可变数组
    val arr1 = new ArrayBuffer[Int]()
    val arr2 = ArrayBuffer(12,23,34,45)
    
    // 2. 访问元素
    println(arr1(0))    // error越界异常
    println(arr2(0))    // 12

    // 3. 添加元素
    arr1 += 11
    println(arr1.mkString(","))    // 数字加在后面
    12 +=: arr1
    println(arr1.mkString(","))    // 数字加在前面
    arr1.append(13)
    arr1.prepend(14)
    arr1.insert(1, 0,10)
    arr1.insertAll(2,arr2)
    arr1.appendAll(arr2)
    arr1.prependAll(arr2)

    // 4. 删除元素
    arr1.remove(3)        // 删除第3个元素
    arr1.remove(0, 10)    // 删除从0开始的10个元素
    arr1 -= 11

  }
}

2.3 可变数组、不可变数组的相互转化

// 1. 可变数组转换为不可变数组
val arr = ArrayBuffer(23,34,45)
val newArr = arr.toArray
println(newArr.mkString(","))

// 2. 不可变数组转换为可变数组
val arrBuffer = newArr.toBuffer
println(arrBuffer)

2.4 多维数组

object MulArray {
  def main(args: Array[String]): Unit = {
    // 1.  创建二维数组
    val array = Array.ofDim[Int](2,3)

    // 2. 访问元素
    array(0)(1) = 10
    array(1)(0) = 21

    // 二位数组相当于保存了两个一维数组的地址。
    println(array.mkString(", "))   // [I@2d209079, [I@6bdf28bb
    // 方式一:for循环输出
    for(i<-0 until array.length; j<- 0 until array(i).length){
      println(array(i)(j))
    }
    // 方式二:使用indices函数
    for(i<-array.indices; j<-array(i).indices){
      print(array(i)(j)+"\t")
      if(j==array(i).length - 1) println()
    }
    // 方式三:增强for
    array.foreach(_.foreach( println ))
  }

}

三、列表List

3.1 不可变List

1)说明

(1)List默认为不可变集合

(2)创建一个List(数据有顺序,可重复)

(3)遍历List

(4)List增加数据

(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化

(6)取指定数据

(7)空列表Nil

object Test_List {
  def main(args: Array[String]): Unit = {

    // 1. 创建一个List
    val list1 = List(23,34,45)
    println(list1)                // List(23, 34, 45)

    // 2. 访问和遍历元素
    println(list1(1))
    list1.foreach(println)

    //3. 添加元素
    val list2 = list1.+:(10)    // :+ 在列表末尾添加元素
    val list3 = 10 +: list1     // +: 在列表开头添加元素
      // ::添加元素
    val list4 = list2.::(51)    // ::表示在列表开头添加元素
    val list4 = Nil.::(15)      // 可以用于在空列表中添加元素
    val list5 = 15 :: Nil       // 这种方法也可以添加元素
      // 结合Nil,可以使用如下创建列表的方法:
    val list6 = 12 :: 23 :: 34 :: 45 :: Nil

    // 4. 合并列表。也可以使用上面::的方式
        // :: 基于list6添加元素,添加的这个元素是一个List列表
    val list7 = list5 :: list6    // List(List(15), 12, 23, 34, 45)
        // ::: 把两个列表的元素进行拆分,合并成一个列表
    val list8 = list5 ::: list6    // List(15, 12, 23, 34, 45)
    val list9 = list5 ++ list6    // 和:::功能一致,底层调用的是:::方法

}

3.2 可变列表ListBuffer

object Test_ListBuffer {
  def main(args: Array[String]): Unit = {
    // 1. 创建可变列表
    val list1 = new ListBuffer[Int]()
    val list2 = ListBuffer(12, 23, 34)

    // 2. 添加元素
    list1.append(11, 22)        // 在list末尾添加元素
    list1.prepend(33, 44)       // 在list开头添加元素
    list1.insert(1, 10, 20)     // 在指定位置(下标为1)插入元素
    
    list1 += 25 += 35            // 在list末尾添加元素
    15 +=: list1                 // 在list开头添加元素

    // 3. 合并list
    val list3 = list1 ++ list2    // list1、list2没有变化,生成新列表list3
    list1 ++= list2               // list1末尾添加list2

    // 4. 修改元素
    list2(1) = 30
    list2.update(2,44)

    // 5. 删除元素
    list2.remove(2)
    list2 -= 30                   // -=删除的是匹配到的第一个元素
  }
}

四、Set集合

默认情况下,Scala使用的是不可变集合。如果想使用可变集合,需要引用scala.collection.mutable.Set包。

4.1 不可变Set

1)说明

(1)Set默认是不可变集合,数据无序

(2)数据不可重复

(3)遍历集合

2)案例实操

object ImmutableSet {
  def main(args: Array[String]): Unit = {
    // 1. 创建Set
    val set1 = Set(12,23,23,31)
    println(set1)                // 数据自动去重

    // 2. 添加元素
    val set2 = set1 + 20
    println(set2)                // 无序,插入数据位置随机

    // 3. 合并Set
    val set3 = Set(12,45,32,34)
    val set4 = set2 ++ set3
    println(set4)

    // 4. 删除元素
    val set5 = set3 - 12
    println(set3)                // set3元素不变
    println(set5)                // set5在set3的基础上少了元素12
  }
}

4.2 可变mutable.Set

object MutableSet {
  def main(args: Array[String]): Unit = {
    // 1. 创建Set
    import mutable.Set
    val set1 = Set(12,23,23,31)
    // 或者在声明时加入包名
    val set1 = mutable.Set(12,23,23,31)

    // 2. 添加元素
    val set2 = set1 + 20
    println(set2)                    // +运算 set1内容不作改变

    set1 += 11                       // 将添加新元素后的集合赋值给set1

    set1.add(12)

    // 3. 删除元素
     set1 -= 11

    set1.remove(12)

    // 4. 合并两个Set
    val set3 = mutable.Set(13,24,36)
    val set4 = set1 ++ set3            // set1、set3元素不变
    set1 ++= set3                      // set1中添加set3的元素
  }
}

五、Map集合

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

5.1 不可变Map

1)说明

(1)创建不可变集合Map

(2)循环打印

(3)访问数据

(4)如果key不存在,返回0

2)案例实操

object ImmutableMap {
  def main(args: Array[String]): Unit = {
    // 1. 创建map
    val map1 = Map[String, Int]("a"->13,"b"->25,"hello"->3)
    println(map1)
    
    // 2. 遍历元素
    map1.foreach(println)
    map1.foreach( (kv: (String, Int)) => println(kv) )

    // 3. 取map中所有的key 或者 value
    for (key <- map1.keys){
      println(s"$key -> $(map1.get(key))")
    }

    // 4. 访问某一个key的value
    println( map1.get("a") )        // Some(13)
    println(map1.get("a").get)      // 13
    // 若key不存在,输出None。但key不存在,无法调用.get方法,回出现异常
    // 为了安全起见,我们有getOrElse方法,若不存在,输出0
    println(map1.getOrElse("c",0))

  }
}

5.2 可变Map

object ImmutableMap {
  def main(args: Array[String]): Unit = {
    // 1. 创建map
    val map1 = mutable.Map[String, Int]("a"->13,"b"->25,"hello"->3)
    println(map1)

    // 2. 添加元素
    map1.put("c", 5)
    map1.put("d", 9)

    map1 += (("e", 7))            // 外层()表示方法调用,内层()表示键值对

    // 3. 删除元素
    map1.remove("e")
    map1 -= "d"

    // 4. 修改元素
    map1.update("c", 5)
    map += (("e", 10))

    // 5. 合并两个Map
    val map2 = Map[String, Int]("aaa"->13,"b"->29,"hello"->5)
    map1 ++= map2                  // map2中的值全部添加到map1中,没有的值添加,有的覆盖
    
  }
}

六、Tuple元组

1)说明

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组

注意:元组中最大只能有22个元素

2)案例实操

(1)声明元组的方式:(元素1,元素2,元素3)

(2)访问元组

(3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶

object TestTuple {
  def main(args: Array[String]): Unit = {
    // 1. 创建元组
    val tuple = Tuple3("hello",1,true)

    // 2. 访问元组
    println(tuple)                        // (hello,1,true)
    // 访问元组的1个元素
    println(tuple._1)                     // hello
    // 交换后输出(swap方法是Tuple2特有方法)
    println(tuple2.swap)                  // (name,2)

    // 3. 遍历元组数据
    for (elem <- tuple.productIterator)
      println(elem)

    // 4. 嵌套元组
    val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
    println(mulTuple._4._2)                // 访问元组中嵌套元组的元素

  }
}

七、集合常用函数

7.1 基本属性和常用操作

1)说明

(1)获取集合长度

(2)获取集合大小

(3)循环遍历

(4)迭代器

(5)生成字符串

(6)是否包含

2)案例实操

object CommonOperation {
  def main(args: Array[String]): Unit = {
    val list = List(1,3,5,7,2,89)
    val set = Set(23,34,523,65)

// (1)获取集合长度
    println(list.length)

// (2)获取集合大小
    println(set.size)

// (3)循环遍历
    for (elem <- list)
      println(elem)

    set.foreach(println)

// (4)迭代器
    for (elem <- list.iterator) println(elem)

// (5)生成字符串
    println(list)
    println(set)
    println(list.mkString("--"))

// (6)是否包含
    println(list.contains(23))
    println(set.contains(523))

  }
}

7.2 衍生集合

1)说明

(1)获取集合的头

(2)获取集合的尾(不是头就是尾)

(3)集合最后一个数据

(4)集合初始数据(不包含最后一个)

(5)反转

(6)取前(后)n个元素

(7)去掉前(后)n个元素

(8)并集

(9)交集

(10)差集

(11)拉链

(12)滑窗

2)案例实操

object DerivedCollection {
  def main(args: Array[String]): Unit = {
    val list1 = List(1,3,5,7,2,89)
    val list2 = List(3,7,2,45,7,4,8,19)

// (1)获取集合的头
    println(list1.head)                // 1

// (2)获取集合的尾(不是头就是尾)
    println(list1.tail)                // List(3, 5, 7, 2, 89)

// (3)集合最后一个数据
    println(list1.last)                // 89

// (4)集合初始数据(不包含最后一个)
    println(list1.init)                // List(1, 3, 5, 7, 2)

// (5)反转
    println(list1.reverse)             // List(89, 2, 7, 5, 3, 1)

// (6)取前(后)n个元素
    println(list1.take(3))             // List(1, 3, 5)
    println(list1.takeRight(4))        // List(5, 7, 2, 89)

// (7)去掉前(后)n个元素
    println(list1.drop(3))             // List(7, 2, 89)
    println(list1.dropRight(4))        // List(1, 3)

// (8)并集
    val union = list1.union(list2)
    println("union: " + union)         // 等同于 ::: list1:::list2
    // (如果是set做丙级,会去重)
    val set1 = Set(1,3,5)
    val set2 = Set(2,3,4)
    val union2 = set1.union(set2)
    println("union2: " + union)         // 等同于 ++ set1++set2


// (9)交集
    val itersection = list1.intersect(list2)    // List(3, 7, 2)

// (10)差集
    val diff1 = list1.diff(list2)
    val diff2 = list2.diff(list1)
    println(diff1)                       // List(1, 5, 89)
    println(diff2)                       // List(45, 7, 4, 8, 19)

// (11)拉链
    println("zip:"+ list1.zip(list2))    // zip:List((1,3), (3,7), (5,2), (7,45), (2,7), (89,4))
    println("zip:"+ list2.zip(list1))    // zip:List((3,1), (7,3), (2,5), (45,7), (7,2), (4,89))

// (12)滑窗
    for( elem <- list1.sliding(3) )      // iterator类型,滑动窗口
      println(elem)                      // 即使数据不全,最后一个窗口也要把全部元素列出来

    for( elem <- list1.sliding(3, 4) )   // iterator类型,滚动窗口.步长为4
      println(elem)   
  }
}

7.3 集合计算初级函数

1)说明

(1)求和

(2)求乘积

(3)最大值

(4)最小值

(5)排序

2)实操

object SimpleFunction {
  def main(args: Array[String]): Unit = {
    val list = List(5,1,8,2,-3,4)
//    (1)求和
    println(list.sum)

//    (2)求乘机
    println(list.product)

//    (3)最大值
    println(list.max)
    // 如果list中不是字符,需要自定义比较方式
    val list2 = List( ("a",5),("b",1),("c",5),("d",1) )
    println( list2.maxBy( (tuple:(String, Int)) => tuple._2 ))
    // 可简写为如下:
    println( list2.maxBy( _._2 ))

//    (4)最小值
    println(list.min)
    println( list2.minBy( _._2 ))

//    (5)排序
//    5.1 sort
    println(list.sorted)            // List(-3, 1, 2, 4, 5, 8)
    // 从大到小排序

    println(list.sorted.reverse)
//    5.2 sortBy
    println(list2.sortBy(_._2))     // List((b,1), (d,1), (a,5), (c,5))

//    5.3 sortWith
    println(list.sortWith( (a:Int, b:Int)=> {a < b} ))
    println(list.sortWith( _ < _ ))
  }
}

7.4 集合计算高级函数

1)说明

(1)过滤filter

遍历一个集合并从中获取满足指定条件的元素组成一个新的集合

(2)转化/映射(map)

将集合中的每一个元素映射到某一个函数

(3)扁平化flatten

(4)扁平化+映射flatMap

注:flatMap相当于先进行map操作,再进行flatten操作

集合中的每个元素的子元素映射到某个函数并返回新集合

(5)分组(groupBy)

按照指定的规则对集合的元素进行分组

(6)简化(归约)reduce

(7)折叠fold

2)实操

object HighLevelFunction {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4,5,6,7,8,9)
//    (1)过滤
//    选取偶数
    val evenList = list.filter( x => x%2==0 )
    println(evenList)
    // 可以省略为
    println(list.filter( _ % 2 == 0 ))

//    (2)转化/映射(map)
//    把集合中的每个数乘2
    println(list.map(_ * 2))
    println(list.map( x => x * x ))

//    (3)扁平化flatten
    val nestedList = List(List(1,2,3),List(4,5),List(6,7,8,9))
    println(nestedList.flatten)        // List(1, 2, 3, 4, 5, 6, 7, 8, 9)

//    (4)扁平化+映射
//     将一组字符串进行分词,并保存成单词的列表
    val strings = List("hello world","hello scala","hello java")
    val splitList = strings.map(string => string.split(" "))    // 分词
    val flattenList = splitList.flatten                         // 打散扁平化
    println(flattenList)                                        // List(hello, world, hello, scala, hello, java)
    // 上面两步可以省略为flatMap
    val flatmapList = strings.flatMap(_.split(" "))             // List(hello, world, hello, scala, hello, java)
    println(flatmapList)

//    (5)分组(groupBy)
//    分成奇偶两组
    val groupBy = list.groupBy(_ % 2)
    val groupBy2 = list.groupBy( data => {
      if(data % 2 == 0) "偶数" else "奇数"
    })
    println(groupBy)            // Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
    println(groupBy2)           // Map(奇数 -> List(1, 3, 5, 7, 9), 偶数 -> List(2, 4, 6, 8))

// 给定一组词汇,按照单词的首字母进行分组
    val wordList = List("china","america","alice","canada","bob","japan")
    println(wordList.groupBy( _.charAt(0) ))    
    // Map(b -> List(bob), j -> List(japan), a -> List(america, alice), c -> List(china, canada))

  }
}
object HighLevelFunction_Reduce {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4)
    
// 1. reduce
    println(list.reduce( _+_ ))            // 10
    println(list.reduceLeft( _+_ ))        // 10
    println(list.reduceRight( _+_ ))       // 10

    val list2 = List(3,4,5,8,10)
    println(list2.reduce( _-_ ))           // -24
    println(list2.reduceLeft( _-_ ))       // -24
    println(list2.reduceRight( _-_ ))      // 6  3-(4-(5-(8-10)))

// 2. fold
    println(list.fold(10)(_+_))            // 20  10 + 1 + 2 + 3 + 4
    println(list.fold(10)(_-_))            // 0   10 - 1 - 2 - 3 - 4
    println(list2.foldRight(11)(_-_))      // -5  3 - (4 - (5 - (8 - (10 -11))))
  }
}

7.5 普通WordCount案例

1)需求

单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果

2)需求分析

object CommonWordCount {
  def main(args: Array[String]): Unit = {
    val stringList = List(
      "hello",
      "hello world",
      "hello scala",
      "hello spark from scala",
      "hello flink from scala"
    )

//    1. 对字符串进行切分,得到一个打散所有单词的列表
    val wordList = stringList.flatMap(_.split(" "))
    println(wordList)

//    2. 相同的单词进行分组
    val groupMap = wordList.groupBy(word=>word)
    println(groupMap)

//    3. 对分组之后的list取长度,得到每个单词的个数
    val countMap = groupMap.map(kv=>(kv._1,kv._2.length))
    println(countMap)

//    4. 将map转换为list,并排序取前三
    val sortList = countMap.toList.sortWith(_._2>_._2).take(3)
    println(sortList)
  }
}

八、队列

1)说明

scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。

2)案例实操

object TestQueue {
  def main(args: Array[String]): Unit = {

// 创建一个可变队列
    val que = new mutable.Queue[String]()
    que.enqueue("a","b","c")
            
    println(que)                  // Queue(a, b, c)
    println(que.dequeue())        // a
    println(que.dequeue())        // b
    println(que)                  // Queue(c)

// 不可变队列
    val que2 = Queue("a","b","c")
    println(que2)                 // Queue(a, b, c)
    val que3 = que2.enqueue("d")
    println(que3)                 // Queue(a, b, c, d)
  }
}

九、并行集合par

1)说明

Scala为了充分说明多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

2)案例实操

object TestPar {
  def main(args: Array[String]): Unit = {

    val result = (1 to 100).map(
      x => Thread.currentThread.getId
    )
    println(result)

    val result2 = (1 to 100).par.map(
      x => Thread.currentThread.getId
    )
    println(result2)
  }
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值