文章目录
前言
你们好我是啊晨
首先呢,内容很多,分为几篇,选择阅读就好,很详细。
请:
一、数组
1、定长数组和变长数组
package cn.bigdata.scala
import scala.collection.mutable.ArrayBuffer
object ArrayDemo {
def main(args: Array[String]) {
//初始化一个长度为8的定长数组,其所有元素均为0
val arr1 = new Array[Int](8)
//直接打印定长数组,内容为数组的hashcode值
println(arr1)
//将数组转换成数组缓冲,就可以看到原数组中的内容了
//toBuffer会将数组转换长数组缓冲
println(arr1.toBuffer)
//用for遍历一个数组,i是数组元素
for(i<- arr1) println(i)
//给数组中的元素赋值,arr1数组名称()小括号里面加下标赋值
arr1(0) = 1
//取值arr1数组名称()小括号里面加下标赋值
arr1(0)
//注意:如果没有new,相当于调用了数组的apply方法,直接为数组赋值
//初始化一个长度为1的定长数组,小括号中为数组的元素
val arr2 = Array[Int](10)
println(arr2.toBuffer)
//定义一个长度为3的定长数组
val arr3 = Array("hadoop", "storm", "spark")
//取值、赋值
val str = arr3(1)
arr3(1) = "storm"
//使用()来访问元素
println(arr3(2))
//
//变长数组(数组缓冲)
//如果想使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包
//小括号中为元素,不是数组长度
//小括号不能省略,里面可以不写元素
val arr01= ArrayBuffer[Int](1,2,3,4)
//小括号能省略,小括号中的只能有一个数字且没有意义
val arr02 = new ArrayBuffer[Int]()
val arr02 = new ArrayBuffer[Int]
val ab = ArrayBuffer[Int]()
//向数组缓冲的尾部追加一个元素
//+=尾部追加元素
ab += 1
//追加多个元素
ab += (2, 3, 4, 5)
//追加一个数组++=
ab ++= Array(6, 7)
//追加一个数组缓冲
ab ++= ArrayBuffer(8,9)
//打印数组缓冲ab
//在数组某个位置插入元素用insert(位置,元素)
ab.insert(0, 2)
//在下标2之前插入6,7
ab.insert(2, 6, 7)
//删除数组某个位置的元素用remove(位置) remove(位置,元素个数)
ab.remove(8)
ab.remove(8,2)
println(ab)
//定长数组与变长数组的转换
arr3 = arr1.toBuffer//arr1还是定长数组,返回一个边长数组, arr3是变长数组
arr2.toArray
}
}
2、遍历数组
1.增强for循环
2.好用的until会生成脚标,0 until 10 包含0不包含10
package cn.bigdata.scala
object ForArrayDemo {
def main(args: Array[String]) {
//初始化一个数组
val arr = Array(1,2,3,4,5,6,7,8)
//增强for循环
for(i <- arr)
println(i)
//如果想要每两个元素一跳
for (i <- 0 until (arr.length,2)){
println(i)
}
//好用的until会生成一个Range
//reverse是将前面生成的Range反转
for(i <- (0 until arr.length).reverse)
println(arr(i))
arr.foreach(println(_))
}
}
3、数组转换
yield关键字将原始的数组进行转换会产生一个新的数组,原始的数组不变
package cn.bigdata.scala
object ArrayYieldDemo {
def main(args: Array[String]) {
//定义一个数组
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)
//map相当于将数组中的每一个元素取出来,应用传进去的函数
val arr04 = arr01.map(x=>x*3)
println(arr04.toBuffer)
val arr05 = arr01.map(_*3)
println(arr05.toBuffer)
//filter是过滤,接收一个返回值为boolean的函数
val arr06 = arr01.filter(_%2==0)
println(arr06.toBuffer)
//更高级的写法,用着更爽
//filter是过滤,接收一个返回值为boolean的函数
//map相当于将数组中的每一个元素取出来,应用传进去的函数
val r = arr.filter(_ % 2 == 0).map(_ * 10)
println(r.toBuffer)
}
}
4、数组常用算法
在Scala中,数组上的某些方法对数组进行相应的操作非常方便!
二、元组
映射是K/V对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值。
如果不理解把下面看完,再回来看会理解的
1、创建元组
这里更正一下,元组的元素最多是22个,函数的参数最多也是22个
元组的创建
//元组的创建
val tuple1 = (1, 2, 3, "heiheihei")
println(tuple1)
//元组的创建,最大能创建22个
val tup01 = Tuple3(1,2,3)
println(tup01)
2、获取元组中的值
var a = (1,2,3,4,"e3rr","123")
//通过productArity来获取元祖的长度
println(a.productArity)
//通过productElement来获取元祖的元素,下标从0开始
println(a.productElement(0))
//通过_下划线来获取元祖的元素,下标从1开始
println(a._1)
3、元组的遍历
// 1
for (i<-tup01.productIterator) {
println("i="+i)
}
// 2
tup01.productIterator.foreach(println)
// 3
tup01.productIterator.foreach(println(_))
// 4
tup01.productIterator.foreach(x=>println(x))
4、将对偶的集合转换成映射
//对偶集合 数组中元素都是元组,元组只有两个元素,
//对偶 元组只有两个元素
val arr = Array(("jerry", 44), ("tom", 55), ("lili", 53))
val map01=arr.toMap
println("map01 = "+map01)
5、拉链操作
zip命令可以将多个值绑定在一起
//拉链操作 将两个数组 通过zip 转换成对偶集合
val name=Array("tom","jerry","xiaoming")
val score =Array(99,88,76,86)
val nameInfo=name.zip(score)
println("name="+nameInfo.toBuffer)
注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的元素个数
三、集合
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质
在Scala中集合有可变(mutable)和不可变(immutable)两种类型,immutable类型的集合初始化后就不能改变了(注意与val修饰的变量进行区别)
1、序列
不可变的序列 :(导包)import scala.collection.immutable._
在Scala中序列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))
package cn.bigdata.collect
object ImmutListDemo {
def main(args: Array[String]) {
//创建一个不可变的集合,长度不能改变,元素也不能改变
val lst1 = List(1,2,3)
//通过 序列名称(下标)获取 序列元素
println(lst1(0))
//var val定义的不可变List,中的元素的值不能改变
//将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 lst7 = lst1.:+("12")
val lst0 = List(4,5,6)
//将2个list合并成一个新的List
val lst8 = lst1 ++ lst0
//将lst1插入到lst0前面生成一个新的集合
val lst9 = lst1 ++: lst0
//将lst0插入到lst1前面生成一个新的集合
val lst10 = lst1.:::(lst0)
println(lst10)
//将lst0插入到lst1后面生成一个新的集合
val lst11 = lst01:::( lst0)
}
}
可变的序列 import scala.collection.mutable._
package cn.bigdata.collect
import scala.collection.mutable.ListBuffer
object MutListDemo extends App{
//构建一个可变列表,初始有3个元素1,2,3
//小括号里面是元素,不是长度
val lst = ListBuffer[Int](1,2,3)
//必须有括号,括号中可以不写元素,没有括号可以编译通过,但运行报错
val lst0 = ListBuffer[Int]()
//创建一个空的可变列表,可以没有括号,可以有括号但里面不能有值
val lst1 = new ListBuffer[Int]
val lst1 = new ListBuffer[Int]()
//取值,改变值
lst1(1)
lst1(1) = 11
//向lst1中追加元素,注意:没有生成新的集合
lst1 += 4
lst1.append(5)
lst1.append(6,7)
//将lst0中的元素追加到lst1中, 注意:没有生成新的集合
lst1 ++= lst0
//将lst0和lst1合并成一个新的ListBuffer 注意:生成了一个集合
val lst2 = lst0 ++ lst1
//将元素追加到lst1的后面生成一个新的集合
val lst3 = lst1 :+ 5
//将元素追加到lst1的前面生成一个新的集合
val lst4 = 5 +: lst1
//将元素追加到lst1的前面生成一个新的集合
val lst6 = lst1.+:(5)
for(i<-lst02)println(i)
val lst03 = lst02.map(x=>println(x))
lst02.foreach(x=>println(x))
lst02.foreach(println(_))
//遍历
for(i <- lst1) println(i)
println("length = "+lst1.length)
println("size = "+lst1.size)
for(i <- 0 to lst1.length-1){
println(lst1(i))
}
for(i <- 0 until lst1.length){
println(lst1(i))
}
lst1.foreach(println)
lst1.foreach(println(_))
lst1.foreach(x=>println(x*10))
lst1.foreach((x:Int)=>println(x*10))
val res01 = lst1.map(_)
val res02 = lst1.map(_*3)
val res03 = lst1.map(x=>x)
val res04 = lst1.map((x:Int)=>x)
val res05 = lst1.filter(_%2==0)
val res06 = lst1.filter(x=>x%2==0)
val res07 = lst1.filter((x:Int)=>x%2==0)
val res08 = lst1.filter(x=> if(x%2==0) true else false)
}
Scala中的集合对象都有foreach和map两个方法。两个方法的共同点在于:都是用于遍历集合对象,并对每一项执行指定的方法。而两者的差异在于:foreach无返回值(准确说返回void),map返回集合对象。运行结果:b.getClass 得到的是void, 而c.getClass得到的是colletion 。foreach和map的运行结果一致。结论就是:foreach 无法代替map. 而map方法却可以代替foreach。
问题:为什么scala提供foreach和map两个方法呢?本人看法是scala做为一种支持函数式编程范式的语言,必然要引入一种机制以支持数学中函数概念,而在数学中函数就是映射,所以scala中有map方法一点都不奇怪。而foreach只是用在不需要对集合执行映射操作,但需要遍历集合时才用到。总而言之,foreach用于遍历集合,而map用于映射(转换)集合到另一个集合。
object arrayTest extends App{
var increase=(x:Int)=>x+1
val someNumbers = List ( -11, -10, - 5, 0, 5, 10)
var b = someNumbers.foreach(increase)
println(b.getClass)
var c = someNumbers.map(increase)
println(c.getClass)
c.foreach((x:Int)=>print(x+" "))
println()
c.map((x:Int)=>print(x+" "))
}
val list = List(1,2,3,4,5,100,102,105,109)
list.foreach((x:Int)=>print(x+" "))
println("")
list.foreach((a:Int)=>print(a +" "))
println("")
//省略参数的类型声明,Scala是可以进行类型推断的
list.foreach(a => print(a + " "))
println("")
//省略了参数也能玩得转
list.foreach(println(_))
list.foreach(print)
2、Set
集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。
如果想要按照已排序的顺序来访问集中的元素,可以使用SortedSet(已排序数据集),已排序的数据集是用红黑树实现的。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
不可变的Set
package cn.bigdata.collect
import scala.collection.immutable.HashSet
object ImmutSetDemo extends App{
val set = Set(1, 2, 3)
println(set)
//后面的括号可以省略
val set1 = new HashSet[Int]()
val set1 = new HashSet[Int]
//将元素和set1合并生成一个新的set,原有set不变
val set2 = set1 + 4
//set中元素不能重复
val set3 = set1 ++ Set(5, 6, 7)
val set4 = Set(1,3,4) ++ set1
println(set4.getClass)
val set05 = set01.-(1,2)
val set06 set01-1
val set5 = HashSet(3,4,5)
}
可变的Set
package cn.bigdata.collect
import scala.collection.mutable
object MutSetDemo extends App{
// Set可变集合的创建,如果import了可变集合,那么后续使用默认也是可变集合
import scala.collection.mutable.Set
val mutableSet = Set(1, 2, 3)
//创建一个可变的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)
}
遍历
for(x <- mutableSet) {
println(x)
}
mutableSet.foreach(println(_))
mutableSet.foreach(x=>println("mutableSet = "+x))
序号 | 方法 | 描述 |
---|---|---|
1 | def +(elem: A): Set[A] | 为集合添加新元素,并创建一个新的集合,除非元素已存在 |
2 | def -(elem: A): Set[A] | 移除集合中的元素,并创建一个新的集合 |
3 | def contains(elem: A): | Boolean 如果元素在集合中存在,返回 true,否则返回 false。 |
4 | def &(that: Set[A]): Set[A] | 返回两个集合的交集 |
5 | def &~(that: Set[A]): Set[A] | 返回两个集合的差集 |
6 | def ++(elems: A): Set[A] | 合并两个集合 |
7 | def drop(n: Int): Set[A]] | 返回丢弃前n个元素新集合 |
8 | def dropRight(n: Int): Set[A] | 返回丢弃最后n个元素新集合 |
9 | def dropWhile(p: (A) => Boolean): Set[A] | 从左向右丢弃元素,直到条件p不成立 |
10 | def max: A | 查找最大元素 |
11 | def min: A | 查找最小元素 |
12 | def take(n: Int): Set[A] | 返回前 n 个元素 |
3、Map
package cn.bigdata. collect
mport scala.collection.mutable
object MutMapDemo extends App{
//创建一个不可变得Map
val map01 = Map[String,Int]("james"->20,"luce"->22)
println(map01("james"))
println(map01("lilei"))//如果k不存在运行报错.NoSuchElementException: key not found: lilei
println(map01.get("james"))
println(map01.getOrElse("james",0))
//创建一个不可变得Map
val map01 = Map[String,Int]("james"->20,"luce"->22)
map01 += (("hadoop", 2))//报错
map01("james") = 23//报错
var map01 = Map[String,Int]("james"->20,"luce"->22)
map01 += (("hadoop", 2))
map01("james") = 23//报错
//创建一个不可变得HashMap
val map02 = new HashMap[String,Int]
map02 += (("hadoop", 2)) //报错
map02("hadoop") = 23//报错
var map02 = new HashMap[String,Int]
map02 += (("hadoop", 2))
map02("hadoop") = 23//报错
//构造可变映射
val map2 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 20)
//创建一个可变得Map,后面的括号可以省略
val map1 = new mutable.HashMap[String, Int]
val map1 = new mutable.HashMap[String, Int]()
//向map中添加数据
map1("spark") = 1
map1 += (("hadoop", 2))
map1.put("storm", 3)
map1+= ("huahua"->12)
println(map1)
//从map中移除元素
map1 -= "spark"
map1.remove("hadoop")
println(map1)
获取元素
i.get ("sex")
i.getOrElse("sex","0")
}
//遍历
for((k,v) <- scores){
println(k+"~~~"+v)
}
for (x <- scores) {
println(x)
println(x._1 + "~~~" + x._2)
}
map1.foreach(x=>println(x))
map1.foreach(x=>println(x._1+"~"+x._2))
var map1 = new mutable.HashMap[String, String]()
var map2 = new immutable.HashMap[String, String]()
map1 += ("ML" -> "hadoop");
map1 += ("DL" -> "spark");
var map11 = map1
map1 += ("ML" -> "Neural NetWork");
println("=============mutable 可变的================")
println(map1.mkString("、"))
println(map11.mkString("、"))
map2 = map2 + ("ML" -> "hadoop");
map2 = map2 + ("DL" -> "spark");
var map22 = map2
map2 += ("ML" -> "Neural NetWork");
println("=============immutable 不可变的================")
println(map2.mkString("、"))
println(map22.mkString("、"))
var a = "123"
a.toInt
4、队列 Queue
队列数据存取符合先进先出策略
不可变多列
package com.zg.day02
object QueueDemo2 {
def main(args: Array[String]): Unit = {
val q1 = scala.collection.immutable.Queue[Int]()
println("q1 = "+q1)//Queue()
val q2 = q1.enqueue(1)//enqueue: 添加在队尾
println("q2 = "+q2)//Queue(1)
val q3 = q2.enqueue(2)
println("q3 = "+q3)//Queue(1, 2)
val q4 = q3.enqueue(5,6)
println("q4 = "+q4)//Queue(1, 2, (5,6))
val q5 = q3.enqueue(List(5,6))
println("q5 = "+q5)//Queue(1, 2, 5, 6)
val q6 = q3.enqueue(Queue(5,6))
println("q6 = "+q6)//Queue(1, 2, 5, 6)
val q7 = q6.drop(1)//删除队首1个元素
println("q7 = "+q7)//Queue(2, 5, 6)
val q8 = q6.drop(2)//删除对首2个元素
println("q8 = "+q8)//Queue(5, 6)
q6.foreach(println(_))//遍历
val q9 = q6.head
println("q9 = "+q9)//Queue(1)
val q10 = q6.head
println("q10 = "+q10)//Queue(2, 5, 6)
}
}
可变队列
//队列的创建
import scala.collection.mutable
val q1 = new mutable.Queue[Int]
println(q1)
//队列元素的追加
q1 += 1;
println(q1)
//向队列中追加List
q1 ++= List(2, 3, 4)
println(q1)
//按照进入队列的顺序删除元素
q1.dequeue()
//删除大于3的元素
q1.dequeueAll(x=>x>3)
println(q1)
//塞入数据
q1.enqueue(9, 8, 7)
println(q1)
//返回队列的第一个元素
println(q1.head)
//返回队列最后一个元素
println(q1.last)
//返回除了第一个以外的元素
println(q1.tail)
四、映射
在Scala中,把哈希表这种数据结构叫做映射
1、构建映射
2、获取和修改映射中的值
好用的getOrElse
注意:在Scala中,有两种Map,一个是immutable包下的Map,该Map中的内容不可变;另一个是mutable包下的Map,该Map中的内容可变
//默认导入的包是import scala.collection.immutable._ 不可变得
案例:
注意:通常我们在创建一个集合是会用val这个关键字修饰一个变量(相当于java中的final),那么就意味着该变量的引用不可变,该引用中的内容是不是可变,取决于这个引用指向的集合的类型
for((k,v) <- scores){
println(k+"~~~"+v)
}
for (x <- scores) {
println(x)
println(x._1 + "~~~" + x._2)
}
五、常用函数
1、map flatmap:
在spark中map函数和flatMap函数是两个比较常用的函数。其中
map:对集合中每个元素进行操作, 将集合中的每一个元素映射到某一个函数。 map将一个函数应用于列表的每一个元素并且将其作为一个新的列表返回
flatMap:对集合中每个元素进行操作然后再扁平化。 flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。 flatMap应用于每个序列元素会返回包含原始列表所有序列内的元素的列表
理解扁平化可以举个简单例子
val arr=Array(("A",1),("B",2),("C",3))
arr.flatMap(x=>(x._1+x._2)).foreach(println)
输出结果为
A
1
B
2
C
3
如果用map
arr.map(x=>(x._1+x._2)).foreach(println)
输出结果
A1
B2
C3
2、化简、折叠
折叠,化简:将二元函数引用于集合中的函数reduce
折叠,化简:fold
fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。可以把reduceLeft看做简化版的foldLeft。相关函数:fold,foldLeft,foldRight,可以参考reduce的相关方法理解。
统计一句话中,各个文字出现的次数
val sentence = "一首现代诗《笑里藏刀》:哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈刀哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈"
//m + (“一” -> 1, “首” -> 1, “哈” -> 1)
val i7 = (Map[Char, Int]() /: sentence)((m, c) => m + (c -> (m.getOrElse(c, 0) + 1)))
println(i7)
val map1 =sentence.foldLeft(Map[Char,Int]())((m,c)=>m+(c->(m.getOrElse(c,0)+1)))
println(map1)
3、扫描
这个理解需要结合上面的知识点,扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存。
val i8 = (1 to 10).scanLeft(0)(_ + _)
println(i8)
val a12 = lst1.scanLeft(1)(_+_)
println("a12 = "+a12)
val a13 = lst1.scanLeft(10)(_-_)
println("a13 = "+a13)
val a14 = lst1.scanRight(1)(_+_)
println("a14 = "+a14)
val a15 = lst1.scanRight(10)(_-_) // 1-(2-(3-(4-(5-10)))) 2-(3-(4-(5-10))) 3-(4-(5-10)) 4-(5-10) 5-10 10
println("a15 = "+a15)
4、迭代器
你可以通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历。
val iterator = List(1, 2, 3, 4, 5).iterator
while (iterator.hasNext) {
println(iterator.next())
}
或:
for(enum <- iterator) {
println(enum)
}
未完。。
感谢观看,下篇持续更新