2.Spark学习(集合用法)

本文详细介绍了Scala中的集合用法,包括数组、Seq、Set、Map的可变与不可变版本,以及元组的使用。还探讨了各种集合方法,如reduce、fold、map、flatMap、filter、groupBy和sortBy。最后通过一个综合实例展示了如何统计单词出现次数。

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

集合用法

1. 集合概述

1.1 简介

  • Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。
    • Seq:是一个有先后次序的值的序列,比如数组或列表。IndexSeq允许我们通过它们的下标快速的访问任意元素。举例来说,ArrayBuffer是带下标的,但是链表不是。
    • Set:是一组没有先后次序的值。在SortedSet中,元素以某种排过序顺序被访问。
    • Map:是一组(键、值)对。SortedMap按照键的排序访问其中的实体。

1.2 可变集合

  • 可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。

  • scala.collection.immutable

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0LUUC6OQ-1655393424628)(assets/1648536124515.png)]

1.3 不可变集合

  • 不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变,所以这里的不可变并不是变量本身的值不可变,而是变量指向的那个内存地址不可变可变集合和不可变集合,在scala中该如何进行区分呢?我们一般可以根据集合所在包名进行区分:

  • scala.collection.mutable

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJl1lurh-1655393424629)(assets/1648536092474.png)]

2. 数组用法

2.1 不可变数组

2.1.1 数组特点

  • Scala默认提供的集合都是不可变。

  • scala中给数组一个特定的类型:Array

  • 可以根据索引访问数组的元素,中括号在scala中表示泛型,所以不能在索引操作中使用,使用小括号

2.1.2 数组定义

// String[]
// 构建Scala中的数组,其实等同于构造Java的数组
val array = new Array[String](3)
// 使用集合的伴生对象构建集合,并同时初始化
val array1 = Array(1,2,3,4)
val array2 = Array(5,6,7,8)
//val array2 = Array.apply(1,2,3,4)

2.1.3 数组访问

  • 可以根据索引访问数组的元素
// 访问
// 可以根据索引访问数组的元素
//array.update(1, "abc")
// 中括号在scala中表示泛型,所以不能在索引操作中使用,使用小括号
array(1) = "abc"

2.1.4 数组遍历

for ( i <- array ) {
	println(i)
}

// foreach方法是一个循环的方法,需要传递一个参数,这个从参数的类型是函数类型
//  函数类型 : Int => U
def foreachFunction(num:Int): Unit = {
	println(num)
}

//array1.foreach(foreachFunction)
//array1.foreach((num:Int)=>{println(num)})
//array1.foreach((num:Int)=>println(num))
//array1.foreach((num)=>println(num))
//array1.foreach(num=>println(num))
array1.foreach(println(_))

2.1.5 运算符操作

package com.gec.demo2


object ScalaDemo {

  def main(args: Array[String]): Unit = {
    //定义不可变数组
    val array1 = Array(1,2,3,4)
    val array2 = Array(5,6,7,8)

    //调用+:方法,参数为5,将参数5添加到数组数据前面
    val ints_1: Array[Int] = array1.+:(5)
    //调用+:方法,参数为5
    val ints_2=5+:array1

    println(ints_1.mkString(","))
    println(ints_2.mkString(","))

    //调用:+方法,参数为5,将参数5添加到数组数据后面
    val ints_3 = array1.:+(5)
    val ints_4=array1:+5
    println(ints_3.mkString(","))
    println(ints_4.mkString(","))
  }
}

2.2 可变数组

2.2.1 概述

  • 导入scala.collection.mutable.ArrayBuffer这个类

2.2.2 用法

package com.gec.demo

import scala.collection.mutable.ArrayBuffer

object Scala02_Collection {

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

    // TODO - 集合 - 数组 - 可变数组
    //val buffer = new ArrayBuffer[String]()
    val buffer = ArrayBuffer("a", "b", "c")
    println(buffer)
    // TODO 操作
    //buffer.append("a", "b", "c", "d")
    // buffer.appendAll(Array("a", "b", "c"))
    //buffer.insert(7, "f")

    //buffer.update(0, "e")
    //buffer(0) = "e"

    //buffer.remove(2)
    //buffer.remove(2,2)

    val strings: ArrayBuffer[String] = buffer - "a"

    println(buffer eq strings)
    println(buffer)
    println(strings)

  }

}

2.3 可变数组和不可变数组转换

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        val buffer = ArrayBuffer(1,2,3,4)
        val array = Array(4,5,6,7)

        // 将不可变数组转换为可变数组
        val buffer1: mutable.Buffer[Int] = array.toBuffer
        // 将可变数组转换为不可变数组
        val array1: Array[Int] = buffer.toArray
    }
}

3. Seq集合

3.1 不可变List

  • 有序、可重复的数据

3.1.1 如何创建List集合

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

        // Seq集合
        val list = List(1,2,3,4)

        // 增加数据
        val list1: List[Int] = list :+ 1
        println(list1 eq list)
        list1.foreach(println)
        val list2: List[Int] = 1 +: list
        list2.foreach(println)
        println("*****************")
        val list3: List[Int] = list.updated(1,5)
        println(list eq list3)
        List3.foreach(println)
    }
}

3.1.2 基本操作

// 数据操作
val ints: List[Int] = list :+ 5
val ints1: List[Int] = 5 +: list

ints.foreach(println)
println("---------------")
ints1.foreach(println)

3.2 可变List

3.2.1 基本语法

import scala.collection.mutable.ListBuffer
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        // 可变集合
        val buffer = new ListBuffer[Int]()
        // 增加数据
        buffer.append(1,2,3,4)
        // 修改数据
        buffer.update(1,3)
        // 删除数据
        buffer.remove(2)
        buffer.remove(2,2)
        // 获取数据
        println(buffer(1))
        // 遍历集合
        buffer.foreach(println)
    }
}

3.2.2 基本操作

import scala.collection.mutable.ListBuffer
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        
        // 可变集合
        val buffer1 = ListBuffer(1,2,3,4)
        val buffer2 = ListBuffer(5,6,7,8)

        // 增加数据
        val buffer3: ListBuffer[Int] = buffer1 :+ 5
        val buffer4: ListBuffer[Int] = buffer1 += 5
        val buffer5: ListBuffer[Int] = buffer1 ++ buffer2
        val buffer6: ListBuffer[Int] = buffer1 ++= buffer2

        println( buffer5 eq buffer1 )
        println( buffer6 eq buffer1 )

        val buffer7: ListBuffer[Int] = buffer1 - 2
        val buffer8: ListBuffer[Int] = buffer1 -= 2
        println( buffer7 eq buffer1 )
        println( buffer8 eq buffer1 )
    }
}

3.2.3 可变集合和不可变集合转换

import scala.collection.mutable
import scala.collection.mutable.ListBuffer
object ScalaCollection{
    def main(args: Array[String]): Unit = {
        
        val buffer = ListBuffer(1,2,3,4)
        val list = List(5,6,7,8)
        // 可变集合转变为不可变集合
        val list1: List[Int] = buffer.toList
        // 不可变集合转变为可变集合
        val buffer1: mutable.Buffer[Int] = list.toBuffer
        
    }
}

3.3 Set集合

3.3.1 不可变Set

3.3.1.1 创建不可变的Set
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val set1 = Set(1,2,3,4)
        val set2 = Set(5,6,7,8)
    }
}

3.3.1.2 基本操作
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val set1 = Set(1,2,3,4)
        val set2 = Set(5,6,7,8)

        // 增加数据
        val set3: Set[Int] = set1 + 5 + 6
        val set4: Set[Int] = set1.+(6,7,8)
        println( set1 eq set3 ) // false
        println( set1 eq set4 ) // false
        set4.foreach(println)
        // 删除数据
        val set5: Set[Int] = set1 - 2 - 3
        set5.foreach(println)

        val set6: Set[Int] = set1 ++ set2
        set6.foreach(println)
        println("********")
        val set7: Set[Int] = set2 ++: set1
        set7.foreach(println)
        println(set6 eq set7)
    }
}

3.3.2 可变Set

3.3.2.1 基本语法
import scala.collection.mutable
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val set1 = mutable.Set(1,2,3,4)
        val set2 = mutable.Set(5,6,7,8)

        // 增加数据
        set1.add(5)
        // 添加数据
        set1.update(6,true)
        println(set1.mkString(","))
        // 删除数据
        set1.update(3,false)
        println(set1.mkString(","))

        // 删除数据
        set1.remove(2)
        println(set1.mkString(","))

        // 遍历数据
        set1.foreach(println)
    }
}

3.3.2.2 基本操作
import scala.collection.mutable
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val set1 = mutable.Set(1,2,3,4)
        val set2 = mutable.Set(4,5,6,7)

        // 交集
        val set3: mutable.Set[Int] = set1 & set2
        println(set3.mkString(","))
        // 差集
        val set4: mutable.Set[Int] = set1 &~ set2
        println(set4.mkString(","))
    }
}

3.4 Map集合

3.4.1 概述

  • Map(映射)是一种可迭代的键值对(key/value)结构。所有的值都可以通过键来获取。Map 中的键都是唯一的。

3.4.2 不可变Map

3.4.2.1 创建map对象
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val map1 = Map( "a" -> 1, "b" -> 2, "c" -> 3 )
        val map2 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )
    }
}

3.4.2.2 运算符操作
package com.gec.demo2
import scala.collection.mutable

object ScalaDemo {

  def main(args: Array[String]): Unit = {
    // 创建空集合
    val empty: Map[String, Int] = Map.empty
    val map2=empty.+(("001",1000),("002",2000),("003",3000))
    val map3 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )
    println(map2)
    val map4=map2.++:(map3)
    println(map4)

    val map5=map2.++(map3)
    println(map5)
    val map6=map3.++(map2)
    println(map6)
  }

}

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

        val map1 = Map( "a" -> 1, "b" -> 2, "c" -> 3 )
        val map2 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )

        // 创建空集合
        val empty: Map[String, Int] = Map.empty
        println(empty)
        // 获取指定key的值
        val i: Int = map1.apply("c")
        println(i)
        println(map1("c"))

        // 获取可能存在的key值
        val maybeInt: Option[Int] = map1.get("c")
        // 判断key值是否存在
        if ( !maybeInt.isEmpty ) {
            // 获取值
            println(maybeInt.get)
        } else {
            // 如果不存在,获取默认值
            println(maybeInt.getOrElse(0))
        }

        // 获取可能存在的key值, 如果不存在就使用默认值
        println(map1.getOrElse("c", 0))
    }
}

3.4.3 可变的map对象

3.4.3.1 基本用法
package com.gec.demo

import scala.collection.mutable

object ScalaCollection_5 {

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

    val map1 = mutable.Map( "a" -> 1, "b" -> 2, "c" -> 3 )
    val map2 = mutable.Map( "d" -> 4, "e" -> 5, "f" -> 6 )

    // 添加数据
    map1.put("d", 4)
    val map3: mutable.Map[String, Int] = map1 + ("e" -> 4)
    println(map1 eq map3)
    val map4: mutable.Map[String, Int] = map1 += ("e" -> 5)
    println(map1 eq map4)

    // 修改数据
    map1.update("e",8)
    map1("e") = 8

    // 删除数据
    map1.remove("e")
    val map5: mutable.Map[String, Int] = map1 - "e"
    println(map1 eq map5)
    val map6: mutable.Map[String, Int] = map1 -= "e"
    println(map1 eq map6)
    // 清除集合
    map1.clear()
  }

}

3.4.3.2 遍历操作
import scala.collection.mutable
object ScalaCollection{
    def main(args: Array[String]): Unit = {

        val map1 = mutable.Map( "a" -> 1, "b" -> 2, "c" -> 3 )
        val map2 = mutable.Map( "d" -> 4, "e" -> 5, "f" -> 6 )

        val set: Set[(String, Int)] = map1.toSet
        val list: List[(String, Int)] = map1.toList
        val seq: Seq[(String, Int)] = map1.toSeq
        val array: Array[(String, Int)] = map1.toArray

        println(set.mkString(","))
        println(list.mkString(","))
        println(seq.mkString(","))
        println(array.mkString(","))

        println(map1.get("a"))
        println(map1.getOrElse("a", 0))

        println(map1.keys)
        println(map1.keySet)
        println(map1.keysIterator)
        println(map1.values)
        println(map1.valuesIterator)
}
}

4. 元组

4.1 概述

  • 在Scala语言中,我们可以将多个无关的数据元素封装为一个整体,这个整体我们称之为:元素组合,简称元组。有时也可将元组看成容纳元素的容器,其中最多只能容纳22个

4.2 用法

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

        // 创建元组,使用小括号
        val tuple = (1, "zhangsan", 30)

        // 根据顺序号访问元组的数据
        println(tuple._1)
        println(tuple._2)
        println(tuple._3)
        // 迭代器
        val iterator: Iterator[Any] = tuple.productIterator

        // 根据索引访问元素
        tuple.productElement(0)
        
        // 如果元组的元素只有两个,那么我们称之为对偶元组,也称之为键值对
        val kv: (String, Int) = ("a", 1)
        val kv1: (String, Int) = "a" -> 1
        println( kv eq kv1 )
    }
}

5. 集合方法

5.1 简单方法

        // TODO - 集合 - 方法
        val array = Array(1,2,3,4)

        println(array.size)
        println(array.length)
        println(array.isEmpty)
        println(array.contains(2))
        println(array.distinct.mkString(","))
        println(array.reverse.mkString(","))

        println(array.mkString(","))
        array.foreach(println)
        array.iterator

5.2 reduce

  • 集合的数据无论是多少,最基本的数据操作其实都是两两计算。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5IE4yH6-1655393424629)(assets/1648543677144.png)]

    	// TODO - 集合 - 方法
            val array = ArrayBuffer(1,2,3,4, 5)
    	// 自定义数据操作的方法
            // 集合的数据无论是多少,最基本的数据操作其实都是两两计算。
            // map => reduce => 简化,规约(聚合)
    
            def reduceFunction(x : Int, y : Int): Int = {
                x + y
            }
    
            //println(array.reduce(reduceFunction))
            //println(array.reduce((x:Int, y:Int)=>{x + y}))
            //println(array.reduce((x:Int, y:Int)=>x + y))
            //println(array.reduce((x, y)=>x + y))
            println(array.reduce(_ - _))  // -13
    

5.3 折叠方法

  • fold方法

    • 折叠, 对集合数据进行简化, 获取最终的一条结果fold方法传递2个部分的参数, 第一个部分表示集合之外的数据, 第二个部分的参数表示数据进行的逻辑处理

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l3QETkxx-1655393424630)(assets/1648782998467.png)]

    package com.gec.demo3
    import scala.collection.mutable
    import scala.collection.mutable.ArrayBuffer
    
    object Scala02_Collection {
    
      def main(args: Array[String]): Unit = {
    
        val array = ArrayBuffer(1,2,3,4)
        val num = 5
    
        println(array.fold(5)(_ + _))
      }
    
    }
    
    

5.4 map方法

  • 功能函数:由集合对象提供函数执行自定义的功能,map => 映射(转换) => K->V

     def main(args: Array[String]): Unit = {
    
            // TODO - 集合 - 方法
            val array = ArrayBuffer(1,2,3,4)
    
            // TODO 功能函数:由集合对象提供函数执行自定义的功能
            //  1. map => 映射(转换) => K->V
            //     a => b
    
            // map方法需要传递一个参数,这个参数的类型为函数类型: Int => B
            def mapFunction( num:Int ): Int = {
                num * 2
            }
    
            //println(array.map(mapFunction))
    
    //        println(array.map(
    //            (num:Int) => {
    //                num * 2
    //            }
    //        ))
    
            println(array.map(_*2))
    
        }
    

5.5 flatMap方法

  • 将整体拆分成个体的操作,称之为扁平化,扁平化操作只能对最外层进行操作

    val array = Array(
    	"Hello Scala", "Hello Hadoop"
    )
    
    //println(array.flatten.mkString(","))
    println(array.flatMap(
    	str => {
            str.split(" ")
    	}
    ).mkString(","))
    

5.6 filter方法

  • filter方法可以对集合中的每一条数据进行筛选过滤

            // TODO - 集合 - 方法
            val array = ArrayBuffer(1,2,3,4)
    
            // filter方法可以对集合中的每一条数据进行筛选过滤
            // 满足条件(true)的数据保留,不满足条件(false)的数据丢弃
            val r = array.filter(
                num => {
                    num % 2 != 0
                }
            )
            println(r)
    
    

5.7 groupBy方法

  • 根据指定的规则对每一条数据进行分组

            // TODO - 集合 - 方法
    //        val array = ArrayBuffer(1,2,3,4)
    //
    //        // 根据指定的规则对每一条数据进行分组
    //        val r = array.groupBy(
    //            num => {
    ////                if ( num % 2 == 0 ) {
    ////                    "偶数"
    ////                } else {
    ////                    "奇数"
    ////                }
    //                num % 2
    //            }
    //        )
    //
    //        println(r)
            val array = ArrayBuffer(
                "Hello", "Scala", "Hadoop", "Spark"
            )
    
            println(array.groupBy(_.substring(0, 1)))
    

5.8 sortBy

  • 排序:通过指定的规则对每一条数据进行排序处理, 默认为升序

            // TODO - 集合 - 方法
            //val array = ArrayBuffer(1,4,2,3)
            val array = ArrayBuffer("1", "11", "2", "3", "22")
    
            // 排序:通过指定的规则对每一条数据进行排序处理, 默认为升序
            println(array.sortBy(
                num => num.toInt
            ))
    

6. 综合实例

6.1 需求

  • 统计单词出现次数

6.2 如何实现

package com.gec.bigdata.scala.chapter07

import scala.collection.mutable.ArrayBuffer
import scala.io.{BufferedSource, Source}

object Scala05_Collection_WordCount {

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

        // TODO 1. 读取文件,获取原始数据
        //  line => Hello Scala
        val source: BufferedSource = Source.fromFile("data/word.txt")
        val lines: Array[String] = source.getLines().toArray
        source.close()

        // TODO 2. 将原始数据进行切分成一个一个的单词
        // "Hello Scala" => "Hello", "Scala"
        val words = lines.flatMap(
            line => {
                line.split(" ")
            }
        )

        // TODO 3. 对分词的结果进行分组操作(相同的单词放置在一起)
        // "Hello", "Hello" => { "Hello"=>List( Hello, Hello ) }
        val wordGroup: Map[String, Array[String]] = words.groupBy(word => word)

        // TODO 4. 对分组后的数据进行数量的统计
        // 如果数据在转换时,无需对key进行操作,只对v进行处理时,可以使用mapValues方法
        // { "Hello"=>List( Hello, Hello ) }
        // =>
        // { "Hello"=>2 }
        val wordCount = wordGroup.mapValues(
            v => {
                v.size
            }
        )

        // TODO 5. 将统计结果打印在控制台
        println(wordCount)

    }

}

6.3 优化写法

package com.gec.bigdata.scala.chapter07

import scala.io.{BufferedSource, Source}

object Scala05_Collection_WordCount_1 {

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

        // TODO 1. 读取文件,获取原始数据
        //  line => Hello Scala
        val source: BufferedSource = Source.fromFile("data/word.txt")
        val lines: Array[String] = source.getLines().toArray
        source.close()

        val wordCount =
            lines
                .flatMap(_.split(" "))
                .groupBy(word => word)
                .mapValues(_.size)

        println(wordCount)

    }

}

val wordCount = wordGroup.mapValues(
v => {
v.size
}
)

    // TODO 5. 将统计结果打印在控制台
    println(wordCount)

}

}


## 6.3 优化写法

~~~ scala
package com.gec.bigdata.scala.chapter07

import scala.io.{BufferedSource, Source}

object Scala05_Collection_WordCount_1 {

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

        // TODO 1. 读取文件,获取原始数据
        //  line => Hello Scala
        val source: BufferedSource = Source.fromFile("data/word.txt")
        val lines: Array[String] = source.getLines().toArray
        source.close()

        val wordCount =
            lines
                .flatMap(_.split(" "))
                .groupBy(word => word)
                .mapValues(_.size)

        println(wordCount)

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值