Scala基础【集合01】

一 集合

Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。

可变集合可以在适当的地方被更新或扩展。这意味着可以修改,添加,移除一个集合的元素。而不可变集合类,相比之下,内容永远不会改变。不过,仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变,所以这里的不可变并不是变量本身的值不可变,而是变量指向的那个内存地址不可变

可变集合和不可变集合,一般可以根据集合所在包名进行区分:

  • scala.collection.immutable
    在这里插入图片描述

  • scala.collection.mutable
    在这里插入图片描述
    在这里插入图片描述

1 数组

不可变数组

严格意义上数组不是集合,是一种组织和管理数据的结构,但scala中给数组一个特定的类型:Array

基本操作:创建,访问,遍历

  def main(args: Array[String]): Unit = {
    val array = new Array[String](3)
    array.update(1,"a")
    for(i <- array){
      println(i)
    }

反编译后的代码如下,所以构建scala中的数组,其实等同于构造java中的数组

String[] array = new String[]{null, "a", null};
赋值

可以根据索引访问数组的元素update(1,"a"),但scala中的中括号表示泛型,所以不能在索引操作中使用,使用小括号即可array(1)="a",这两种赋值方式完全相同

创建数组的同时进行初始化,使用集合的伴生对象创建对象,同时进行初始化

val array = Array(1,2,3,4)
val array1 = Array.apply(1,2,3,4)

反编译后的代码为

int[] var10000 = new int[]{1, 2, 3, 4};
访问

集合分为可变集合和不可变集合,scala默认提供的集合都是不可变的,每一次添加操作都会产生新的集合

  def main(args: Array[String]): Unit = {
    val array = Array(1,2,3,4)

    val ints = array.+:(5)
    val ints1 = array.:+(5)

    println(array eq ints)  //false
    println(array eq ints1) //false
    println(ints eq ints)   //false

    for(i <- array){
      println(i)            //1,2,3,4
    }

查看ints,ints1,mkString,生成字符串,第一次遍历使用 ,隔开,第二次遍历使用-隔开

	println(ints.mkString(","))   //5,1,2,3,4
    println(ints1.mkString("-"))  //1-2-3-4-5

如果运算符以冒号结尾,则运算规则从后向前计算

    val ints = array.+:(5)	//等同于
    val ints = 5 +: array
    
    val ints1 = array.:+(5)	//等同于
    val ints1 = array :+ 5
    val ints2 = array ++ array1
    println(ints2.mkString(","))  //1,2,3,4,5,6,7,8
遍历

foreach是一个循环的方法,需要传递一个参数,参数的类型是函数类型:Int => U

    def foreachFunction(num:Int): Unit ={
      println(num)
    }
    array.foreach(foreachFunction)    //1,2,3,4

array将每个数字传递给函数的num,foreach循环调用foreachFunction

使用匿名函数代替声明的函数

array.foreach((num:Int)=>{println(num)})

使用函数至简原则进行化简

array.foreach(println(_))
其他操作

多维数组

var myMatrix = Array.ofDim[Int](3,3)
myMatrix.foreach(list=>println(list.mkString(",")))

输出内容为

0,0,0
0,0,0
0,0,0

合并数组

val arr3: Array[Int] = Array.concat(arr1, arr2)
arr3.foreach(println)

创建指定范围的数组,左闭右开

val arr4: Array[Int] = Array.range(0,2)
arr4.foreach(println)

创建数组并按照特定值(-1)填充指定数量的数组

val arr5:Array[Int] = Array.fill[Int](5)(-1)
arr5.foreach(println)

可变数组

直接在原数组的基础上进行修改,内容可变

  def main(args: Array[String]): Unit = {
    val buffer = new ArrayBuffer[Int]()
    println(buffer)          //ArrayBuffer()

    buffer.append(1,2,3,4)			//ArrayBuffer(1, 2, 3, 4)
    buffer.appendAll(Array(1,2,3))    //ArrayBuffer(1, 2, 3, 4, 1, 2, 3)
    buffer.insert(1,5)      //ArrayBuffer(1, 5, 2, 3, 4, 1, 2, 3)
    //buffer.insert(100,1)  //IndexOutOfBoundsException
    buffer.update(0,10)     //ArrayBuffer(10, 5, 2, 3, 4, 1, 2, 3)
    buffer(0) = 9           //ArrayBuffer(9, 5, 2, 3, 4, 1, 2, 3)
    buffer.remove(0)        //ArrayBuffer(5, 2, 3, 4, 1, 2, 3)
    buffer.remove(0,3)      //ArrayBuffer(4, 1, 2, 3)
    println(buffer) 
    
    // 使用 ++= 运算符会更新之前的集合,不会产生新的数组
    val buffer5: ArrayBuffer[Int] = buffer1 ++= buffer2
  }

注意以下方法会产生新的数组

val ints = buffer - 4
println(ints eq buffer)   //false
println(ints)             //ArrayBuffer(1, 2, 3)
println(buffer)           //ArrayBuffer(4, 1, 2, 3)

 // 使用 ++ 运算符会产生新的集合数组
val buffer4: ArrayBuffer[Int] = buffer1 ++ buffer2

使用伴生对象,在创建数组的同时进行初始化

val buffer = ArrayBuffer(1,2,3,4)

不可变数组与可变数组的相互转换

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
}

java集合和scala集合间的互相转换

//java ==> scala
import scala.collection.JavaConverters._
val list = new java.util.ArrayList()
list.asScala.foreach(println)

//scala ==> java
val java = List(1,2,3,4).asJava

2 集合提供的方法

scala关注的重点在于集合作为一个容器是如何对数据进行操作的,不关心底层是如何存储,管理数据的,是数组,List,Set,Map区别不大,所以重点集中到提供的几个功能

常用的方法

println(array.size)    				    //6
println(array.length)  					//6
println(array.isEmpty)   				//false
array.contains(println(3))  			//  3
println(array.distinct.mkString(","))   //1,2,3,4,5
println(array.reverse.mkString(","))    //5,4,4,3,2,1

遍历相关

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

从集合获取部分元素

val buffer = ArrayBuffer(1,2,3,4)

println(buffer.head)     //1
println(buffer.tail)     //ArrayBuffer(2, 3, 4)
println(buffer.tails)    //<iterator>
println(buffer.last)     //4
println(buffer.init)     //ArrayBuffer(1, 2, 3)
println(buffer.inits)    //<iterator>

//取前几个
println(buffer.take(3))         //ArrayBuffer(1, 2, 3)
println(buffer.takeRight(2))    //ArrayBuffer(3, 4)
println(buffer.drop(1))         //ArrayBuffer(2, 3, 4)
println(buffer.dropRight(1))    //ArrayBuffer(1, 2, 3)

与计算相关的方法

println(array.sum)      //10
println(array.max)      //4
println(array.min)      //1
println(array.product)  //24

如果没有现成提供的方法,需要自定义数据操作的方法,集合的数据无论有多少,最基本的数据操作其实都是两两计算

map ==> reduce ==> 简化,规约,集合

println(array.reduce((x,y) => x - y))	//-8
println(array.reduce(_ - _))			//-8
println(array.reduceLeft(_-_))			//-8
println(array.reduceRight(_-_))			//-2

reduceLeft从左边加括号:(((1 - 2)- 3)- 4)

reduceRight从右边加括号:(1 -(2 -(3 - 4)))

与集合外部的数据进行操作

val array = ArrayBuffer(1,2,3,4)
val num = 5
println(array.fold(num)(_ - _))      //-5,先执行5 - 1-->5,1,2,3,4,从左边加括号
println(array.foldLeft(num)(_-_))    //-5,将5放在左边,从左边加括号
println(array.foldRight(num)(_-_))   //3,将5放在右边,从右边加括号
//将两两计算的临时结果保留下来(检验)
println(array.scan(num)(_ - _))       //ArrayBuffer(5, 4, 2, -1, -5)
println(array.scanRight(num)(_ - _))  //ArrayBuffer(3, -2, 4, -1, 5)

功能函数

由集合对象提供函数执行自定义的功能

将数组整体乘n倍:map => 映射(转换) => 通过K可以得到V

map方法需要传递一个参数,参数的类型为函数类型:Int => B

提供的功能就是给一个a可以经过运算变为b

 def main(args: Array[String]): Unit = {
    val array = ArrayBuffer(1,2,3,4)
    def mapFunction( num:Int): Int = {
      num * 2
    }
    println(array.map(mapFunction))
  }

使用匿名函数

println(array.map(
  (num:Int) => {
    num * 2
  }
))

至简原则

println(array.map(_ * 2))

将整体拆分成个体的操作,如将一个二维数组拆分成一个一维数组,称为扁平化,默认只对最外层进行操作

 def main(args: Array[String]): Unit = {
    val array = ArrayBuffer(
      ArrayBuffer(
        ArrayBuffer(1,2),ArrayBuffer(5,6)
      ),ArrayBuffer(
        ArrayBuffer(3,4),ArrayBuffer(7,8)
      )
    )
    println(array.flatten.flatten)
  }

如果需要自定义扁平化过程,使用flatMap方法

将以下单词分开

val array = Array(
  "hello scala","helo hadoop"
)
println(array.flatten.mkString(","))

println(array.flatMap(
  str => str.split(" ")
).mkString(","))

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

满足条件的数据保留,不满足条件的数据丢弃

按照偶数过滤,是偶数留下,不是过滤掉

 def main(args: Array[String]): Unit = {
    val array = ArrayBuffer(1,2,3,4)
    val r = array.filter(
      num => {
        num % 2 == 0
      }
    )
    println(r)
    val rr = array.filter(_ % 2 == 0)
    println(rr)
  }

groupBy方法可以根据指定的规则对每一条数据进行分组

按照奇偶数进行分组

 def main(args: Array[String]): Unit = {
    val array = ArrayBuffer(1,2,3,4)
    val r = array.groupBy(
      num => {
        if (num % 2 == 0)
          "偶数"
        else
          "奇数"
      }
    )
    println(r)
    println(array.groupBy(_ % 2 == 0))
    println(array.groupBy(_ % 2))

将相同首字母的单词放到一组

 val arrayBuffer = ArrayBuffer(
      "hello","scala","hadoop","spark"
    )
    println(arrayBuffer.groupBy(_.substring(0, 1)))

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

将数字按照数字的规则进行排序

 val array = ArrayBuffer(1,3,4,2)
    println(array.sortBy(
      num => num
    ))

将字符串分别按照字典序和数字的规则进行排序

	val array = ArrayBuffer("1","11","2","22","3")
    println(array.sortBy(num => num))
    println(array.sortBy(num => num.toInt))

按照降序排序

println(array.sortBy(num => num.toInt)(Ordering.Int.reverse))

完成WordCount

  • 读取文件,获取原始数据,获取到的是一行一行的数据(eg. hello scala)
  • 将原始数据切分成一个一个的单词(eg. hello,scala)
  • 对分词的结果进行分组操作,相同的单词放到一起(eg. hello,hello => {hello => List(hello,hello)}
  • 对分组后的数据进行数量统计(eg.{hello => List(hello,hello)} => {hello,2})
  • 将统计结果打印在控制台
  def main(args: Array[String]): Unit = {
    //获取数据,将每一行的数据分别存储到一个数组中,关闭资源
    val source: BufferedSource = Source.fromFile("data/word.txt")
    val lines: Array[String] = source.getLines().toArray
    source.close()
    //拆分
    val words: Array[String] = lines.flatMap(
      line => line.split(" ")
    )
    //分组
    val wordGroup: Map[String, Array[String]] = words.groupBy(word => word)
    //数量统计,如果数据在转换时,无需对key进行操作,只对v进行处理,可以使用mapValues方法
    val wordCount: Map[String, Int] = wordGroup.mapValues(
      v => v.size
    )
    println(wordCount)
  }

升级版

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

    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)
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneTenTwo76

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值