scala的数组、映射、元组和集合

来源:互联网 发布:mysql语句区分大小写吗 编辑:程序博客网 时间:2024/06/05 05:53

一、数组

1.1定义数组

scala> val arr = new Array[Int](10)

arr: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)


scala> arr(0)=1

scala> arr(1)=2

scala>val arr1 = Array(1,2,3,4)

arr1:Array[Int] = Array(1,2,3,4)

注:直接给arr1赋值了,其实是调用了它的静态方法apply

1.2定长数组和变长数组

//初始化一个长度为8的定长数组,其所有元素均为0    val arr1 = new Array[Int](8)    //直接打印定长数组,内容为数组的hashcode值    println(arr1)    //将数组转换成数组缓冲,就可以看到原数组中的内容了    //toBuffer会将数组转换长数组缓冲    println(arr1.toBuffer)    //注意:如果new,相当于调用了数组的apply方法,直接为数组赋值    //初始化一个长度为1的定长数组    val arr2 = Array[Int](10)    println(arr2.toBuffer)    //定义一个长度为3的定长数组    val arr3 = Array("hadoop", "storm", "spark")    //使用()来访问元素    println(arr3(2))    //////////////////////////////////////////////////    //变长数组(数组缓冲)    //如果想使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包    val ab = ArrayBuffer[Int]()    //向数组缓冲的尾部追加一个元素    //+=尾部追加元素    ab += 1    //追加多个元素    ab += (2, 3, 4, 5)    //追加一个数组++=    ab ++= Array(6, 7)    //追加一个数组缓冲    ab ++= ArrayBuffer(8,9)    //打印数组缓冲ab    //在数组某个位置插入元素用insert    ab.insert(0, -1, 0)    //删除数组某个位置的元素用remove    ab.remove(8, 2)    println(ab)


1.3遍历数组

1.增强for循环

2.好用的until会生成脚标,0 until 10 包含0不包含10

 //初始化一个数组    val arr = Array(1,2,3,4,5,6,7,8)    //增强for循环    for(i <- arr)      println(i)    //好用的until会生成一个Range    //reverse是将前面生成的Range反转    for(i <- (0 until arr.length).reverse)      println(arr(i))

scala> val arr = Array(1,2,3,4,5,6,7)
arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7)


scala> for(i <-(0 until arr.length).reverse)  print(arr(i))
7654321

1.4数组转换

生成一个元素是原数组10倍的数组
scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)


scala> for(i <- a) yield i*10
res0: Array[Int] = Array(10, 20, 30, 40, 50)


scala> val b = for(i <- a) yield i*10
b: Array[Int] = Array(10, 20, 30, 40, 50)


scala> b
res1: Array[Int] = Array(10, 20, 30, 40, 50)


scala> a.map((x:Int)=>x*10)
res2: Array[Int] = Array(10, 20, 30, 40, 50)


scala> a.map(x=>x*10)
res3: Array[Int] = Array(10, 20, 30, 40, 50)


scala> a.map(_*10)
res4: Array[Int] = Array(10, 20, 30, 40, 50)

//定义一个数组    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)    //将偶数取出乘以10后再生成一个新的数组    val res = for (e <- arr if e % 2 == 0) yield e * 10    println(res.toBuffer)    //更高级的写法,用着更爽    //filter是过滤,接收一个返回值为boolean的函数    //map相当于将数组中的每一个元素取出来,应用传进去的函数    val r = arr.filter(_ % 2 == 0).map(_ * 10)    println(r.toBuffer)
注:map相当于将数组中的每一个元素取出来

1.5数组的常用算法


1.6练习

package com.heres.scala/** * 大数据是数据的集合以及对数据集合的操作技术的统称,具体来书: * 1.数据集合:会涉及数据的搜集、存储等,搜集会有很多技术,存储现在比较经典的是使用Hadoop,也有很多情况使用Kafka; * 2.对数据集合的操作技术:目前全球最火爆的是Spark; *  * spark的框架实现语言是Scala,首选的应用程序开发语言也是Scala,所以Scala对集合以及集合操作的支持就至关重要且必须异常强大; * 一个补充说明:可能是巧合,spark中对很多数据的操作的算子和Scala中对集合的操作算子是一样的! * 也就是说,掌握Scala中集合操作,基本上就可以直接开发spark代码了。 *  * 关于scala中数组的创建与操作: * 1.最原始的创建数据的方式是形如:val arry = new Array[Int](5),指定数组的类型是Int且固定长度是5个元素; * 2.最常用和经典的创建数组的方式是形如  val arry1 = Array[Int](1,2,3,4,5),直接通过Array类名并传入参数的方式来创建数组实例,在背后的实现 * 是调用Array的工厂方法模式apply来构建出数组及数组的内容的; * 3.关于Array本身在底层的实现是借助了Jvm平台上的Java语言的数组实现,是不可变的! * 4.如果想使用可变数组的话,首先需要导入import scala.collection.mutable.ArrayBuffer,然后使用ArrayBuffer这个可变数组 * 5.关于ArrayBuffer增加元素默认情况下都是在ArrayBuffer末尾增加元素,效率非常高! * 6.当需多线程并发操作时,把ArrayBuffer变成Array就非常重要。其实,即使是Array,其本身虽然不可变动(元素不可删减),但是我们可以修改Array中每个元素的内容,所以多线程操作的时候 * 还是并需考虑并发写的问题。 * 7.如果想在已经有的数组的基础上通过作用于每个元素来生成新的元素构成的新数组,则可以通过yied语法来完成。这在大数据中意义重大。 * 第一点:它是在不修改已经有的Array的内容的基础上完成的,非常适合于大数据的处理; * 第二点:在大数据中处理中,例如spark中业务操作的核心思想类似于yield,来通过使用function对每个元素操作获得新的元素构成的新的集合,例如MapPartionsRDD * 8.集合的操作往往可以通过丰富的操作算子。例如filter来过滤符合条件的元素;例如map来进行每个元素的加工 */object HelloCollection {  def main(args: Array[String]): Unit = {    val arry = new Array[Int](5)    val arry1 = Array(1,2,3,4,5)//在这里可以去掉[Int]这个泛型类型,是因为scala有类型推到的能力,而我们已经传进了当前数组Array的值所以可以根据值来推导出类型    //2    //val arry1 = Array.apply(1,2,3,4,5)    arry(0) = 10 //数据的索引下标是从0开始 的        for(item <- arry) println(item)    for(item <- arry1) println("scala元素:"+item)        //4    import scala.collection.mutable.ArrayBuffer    val arrayBuffer = ArrayBuffer[Int]()    arrayBuffer += 1    arrayBuffer += 2    arrayBuffer += (3,4,5,6)    arrayBuffer ++= Array(7,8,9)    //5    arrayBuffer.insert(0, 8888,4444)    arrayBuffer.remove(arrayBuffer.length-1)    arrayBuffer.toArray//当需多线程并发操作时,把ArrayBuffer变成Array就非常重要    for(item <- arrayBuffer) println("arrayBuffer "+item)         for(i <- 0 until (arrayBuffer.length,1)) print(arrayBuffer(i)+" ")    println()    //反转    for(i <- (0 until (arrayBuffer.length,1)).reverse) print(arrayBuffer(i)+" ")    val arrayto = arrayBuffer.toArray    scala.util.Sorting.quickSort(arrayto)//对数组进行升序排序    print("arrayto Sorting: ")    for(i <- 0 to arrayto.length-1) print(arrayto(i)+" ")    println()    //7    val arrayAddeOne = for(item <- arry1) yield item + 1    println(arrayAddeOne.mkString(","))        val arrayAddeEven = for(item <- arry1 if item%2 == 0) yield item + 100    println(arrayAddeEven.mkString(" _ "))    //8    println(arry1.filter { x => x % 3 == 2 }.mkString(" "))    println(arry1.filter { _ % 3 == 2 }.map(_*10).mkString(" "))      }}


二、映射(Map)

在Scala中,把哈希表这种数据结构叫做映射

2.1构建映射


注:构建映射分两种方法:

a.  val scores = Map("tom" -> 85,"jerry" -> 99)

b. val scores = Map(("tom",88),("jerry",99))

2.2获取、修改映射中的值



注意:在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变

例子:


三、元组(Tuple)

映射是K/V对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值。

3.1创建元组


3.2获取元组中的值


3.3将对偶的集合转换成集合


3.4拉链操作


注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数

Map和Tuple的代码示例:

package com.heres.scala/** * Map:key-value,key既是值的索引,同时key也是按照hash的方式排列的。 * 为什么Map这种key-value类型的数据结构非常重要呢? * a.造物的哲学来讲,key相当于是value的名字 * b.海量数据,基于Map检索非常快;(数组就非常慢,尤其修改的时候) *  * Tuple:可以容纳不同的类型数据 (Array数组中放置数据的类型必须一致或者是子类型) *  * 1.默认情况下Map构造的是不可变的集合,里面的内容不可修改,一旦修改就变成新的Map,原有的Map内容保持不变; * 2.Map的实例是调用工厂方法模式apply来构造Map实例,而需要主要的是Map是接口,在apply中 使用具体的实现 * 3.如果想直接new 出Map实例,则需要使用HashMap等具体的Map子类; * 4.查询一个Map中的值一定采用getOrElse的语法,一方面在key不存在的情况下不报异常,另外提供默认值,在spark中许多默认的配置都是通过getOrElse的方式 * 实现的; * 5.使用scala.collection.immutable.SortedMap可以得到以key排序的Map集合; * 6.LinkHashMap可以记住插入的数据的顺序,这在实际开发中非常有用。 *  * 7.Tuple可以用许多不同类型额的数据,例如:("wangwu","male",23,"I love scala") * 8.在企业级开发中,Tuple会经常用来表达数据结构,以及使用tulpe来处理业务逻辑; * 9.tuple的另外一个非常重要的使用是作为函数的返回值,在tuple中返回若干个值;以SparkContext为例来说明 * val (sched,ts) = SparkContext.createTaskSchedular(this,master) * _schedulerBackend = sched * _taskScheduler = ts   */object HelloMap {  def main(args: Array[String]): Unit = {    //调用了Map的工厂方法apply来构造Map实例,而需要注意的是Map是接口,在apply中使用了具体的实现    val bigdata = Map("Spark" ->6,"hadoop"->11)    val persons = scala.collection.immutable.SortedMap(("zhangsan",30),("wangwu",22),("hadoop",10))         //bigdata("Spark") = 10 //value update is not a member of scala.collection.immutable.Map[String,Int]        val programingLanguage = scala.collection.mutable.Map("scala"->13,"java"->"23")    programingLanguage("scala") = 15//可修改        for((name,age) <- programingLanguage) println(name+":"+age)    //  println(programingLanguage("python"))//报异常:java.util.NoSuchElementException: key not found: python   //4    println(programingLanguage.getOrElse("python",16))    //3    val personsInfo =new scala.collection.mutable.LinkedHashMap[String,Int]    personsInfo += ("Spark" ->6,"hadoop"->11)   // personsInfo -= ("Spark")        for((name,age) <- personsInfo) println(name+"->"+age)    //只打印key    for(key <-personsInfo.keySet) println(key)    //只打印value    for(value <-personsInfo.values) println(value)        val re = for((name,age) <- bigdata) yield (age ,name)    for((name,age) <- re) println(name+":"+age)         for((name,age) <- persons) println(name+":"+age)  //**************************************************************************************************//    val info = ("wangwu","male",23,"I love scala")    println("Tuple info "+info._4)  } }


四、集合

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

在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)

4.1序列

不可变的序列import scala.collection.immutable._

在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。

9 :: List(5, 2)  :: 操作符是将给定的头和尾创建一个新的列表

注意:: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于9 :: (5 :: (2 :: Nil))

//创建一个不可变的集合    val lst1 = List(1,2,3)    //将0插入到lst1的前面生成一个新的List    val lst2 = 0 :: lst1    val lst3 = lst1.::(0)    val lst4 = 0 +: lst1    val lst5 = lst1.+:(0)    //将一个元素添加到lst1的后面产生一个新的集合    val lst6 = lst1 :+ 3    val lst0 = List(4,5,6)    //将2个list合并成一个新的List     val lst7 = lst1 ++ lst0    //将lst0插入到lst1前面生成一个新的集合 ????    val lst8 = lst1 ++: lst0    //将lst0插入到lst1前面生成一个新的集合    val lst9 = lst1.:::(lst0)    println(lst9)


可变的序列import scala.collection.mutable._

//构建一个可变列表,初始有3个元素1,2,3  val lst0 = ListBuffer[Int](1,2,3)  //创建一个空的可变列表  val lst1 = new ListBuffer[Int]  //向lst1中追加元素,注意:没有生成新的集合  lst1 += 4  lst1.append(5)  //将lst1中的元素追加到lst0中, 注意:没有生成新的集合  lst0 ++= lst1  //将lst0和lst1合并成一个新的ListBuffer 注意:生成了一个集合  val lst2= lst0 ++ lst1  //将元素追加到lst0的后面生成一个新的集合  val lst3 = lst0 :+ 5

4.2集合

不可变的set

package cn.itcast.collectimport scala.collection.immutable.HashSetobject ImmutSetDemo extends App{  val set1 = new HashSet[Int]()  //将元素和set1合并生成一个新的set,原有set不变  val set2 = set1 + 4  //set中元素不能重复  val set3 = set1 ++ Set(5, 6, 7)  val set0 = Set(1,3,4) ++ set1  println(set0.getClass)}

可变的set

package cn.itcast.collectimport scala.collection.mutableobject MutSetDemo extends App{  //创建一个可变的HashSet  val set1 = new mutable.HashSet[Int]()  //向HashSet中添加元素  set1 += 2  //add等价于+=  set1.add(4)  set1 ++= Set(1,3,5)  println(set1)  //删除一个元素  set1 -= 5  set1.remove(2)  println(set1)}


4.3Map

package cn.itcast.collectimport scala.collection.mutableobject MutMapDemo extends App{  val map1 = new mutable.HashMap[String, Int]()  //向map中添加数据  map1("spark") = 1  map1 += (("hadoop", 2))  map1.put("storm", 3)  println(map1)  //从map中移除元素  map1 -= "spark"  map1.remove("hadoop")  println(map1)}

5简单练习

5.1

 //创建一个List
    val lst0 = List(1,7,9,8,0,3,5,4,6,2)


    //将st0中每个元素乘以10后生成一个新的集合

scala> val b = for(i <- a) yield i*10
b: Array[Int] = Array(10, 20, 30, 40, 50)

scala> a.map((x:Int)=>x*10)
res2: Array[Int] = Array(10, 20, 30, 40, 50)

scala> a.map(x=>x*10)
res3: Array[Int] = Array(10, 20, 30, 40, 50)

scala> a.map(_*10)
res4: Array[Int] = Array(10, 20, 30, 40, 50)


    //将lst0中的偶数取出来生成一个新的集合
scala> lst0.filter(_%2==0).map(_*10)


    //将lst0排序后生成一个新的集合
lst0.sorted

    //反转顺序
lst0.sorted.reverse

    //将lst0中的元素4个一组,类型为Iterator[List[Int]]
lst0.grouped(4)

    //将Iterator转换成List
lst0.grouped(4).toList

    //将多个list压扁成一个List
lst0.grouped(4).toList.flatten

5.2
val lines = List("hello tom hello jerry", "hello jerry", "hello kitty")
    //先按空格切分,在压平
lines.map(_.split(" ")).flatten
lines.flatMap(_.split(" "))

5.3
    //并行计算求和
lst0.par
lst.par.reduce(_+_)
    //化简:reduce
    //将非特定顺序的二元操作应用到所有元素
reduce -> reduceLeft
    //安装特点的顺序,par转换成并行化集合,进行并行计算,fold表示加上原来的值
lst0.par.fold(0)(_+_)


    //折叠:有初始值(无特定顺序)
lst0.par.fold(0)(_+_)
    //折叠:有初始值(有特定顺序)
lst0.par.fold(10)(_+_)


    //聚合
    val arr = List(List(1, 2, 3), List(3, 4, 5), List(2), List(0))

arr.aggregate(0)(_+_.sum,_+_)


    val l1 = List(5,6,4,7)
    val l2 = List(1,2,3,4)
    //求并集
val r1 = l1.union(l2)
    //求交集
val r2 = l1.intersect(l2)
    //求差集
val r3 = l1.diff(l2)
r3: List[Int] = List(5, 6, 7)
val r3 = l2.diff(l1)
        r4: List[Int] = List(1, 2, 3)
    println(r3)



5.4进行wordcount统计
val lines = List("hello tom hello jerry", "hello jerry", "hello kitty")

法1:
lines.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).map(t=>(t._1, t._2.size)).toList.sortBy(_._2).reverse

分析:


map((_, 1))把元素变成元组


groupBy(_._1)按照元组的第一个元素分组


map(t=>(t._1, t._2.size))统计List的大小


toList



法2:
lines.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.foldLeft(0)(_+_._2))


mapValues())对value进行操作,key保持不动


mapValues(_.foldLeft(0)(_+_._2)),如果vale的大小不是由一个一个的构成,第一个“_”拿到的是List,第二个“_”表示累加后的结果






原创粉丝点击