目录
4.scala trait 特质,相当于Java的接口,但更强大
Scala 安装及应用
Scala简介
是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。
Scala 运行在Java虚拟机上,并兼容现有的Java程序。
Scala 源代码被编译成Java字节码,所以它可以运行于JVM之上,并可以调用现有的Java类库。
Scala安装:
1.window安装:
Scala 官网 http://www.scala-lang.org/下载 Scala 编译器安装包,
http://spark.apache.org/docs/latest/ 可查看 spark版本对应采用的scala版本
本教程采用 spark 2.4.5 最新release版本:
Spark runs on Java 8, Python 2.7+/3.4+ and R 3.1+.
For the Scala API, Spark 2.4.5 uses Scala 2.12. You will need to use a compatible Scala version (2.12.x).
下载 scala-2.12.11.msi 后点击下一步就可以了.
2.Linux安装
Scala官网下载 scala-2.12.11.tgz 包,上传服务器,
tar -zxvf scala-2.12.11.tgz -C /安装目录
修改环境变量不赘述.
3.启动:
shell or cmd :
scala #启动交互式命令窗口
:quit #退出
:help
Scala基础应用
1.数据类型,变量,方法,函数
object HelloScala {
def test1(): Unit={
/*
Java 基本数据类型8种:Byte、Short、Int、Long、Float、Double、Char、Boolean
scala 数据类型:9种: Byte、Short、Int、Long、Float、Double、Char、Boolean、Unit 类型,
另外还有 :String字符序列
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最底端,它是任何其他类型的子类型
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类
AnyVal 所有值类型(上文9种)的基类, 它描述的是值,而不是代表一个对象。
scala 所有数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的
Python 中的变量类型:
6大标准数据类型:
不可变数据类型:Number(数字)、String(字符串)、Tuple(元组)
可变数据类型:List(列表)、Dictionary(字典)、Set(集合)
Python3 Number 支持 int、float、bool、complex(复数)4种数值类型
Python 中,变量就是变量,它没有类型,我们所说的"类型"是变量所指的内存中对象的类型。
*/
// 变量定义 val/var 变量名:type = 变量值 ,不带返回值,编译器会自动推测返回类型.
val name = "字符串" // 不可变变量 类似 Java final修饰的变量
var name1: String = "字符串1" // 可变变量
var floatnum: Float = 12.345f
printf(name) // 不换行输出
print(name,name1)
name1="1321"
println(name,name1="1321") // 换行输出
// 'f'插值器允许创建一个格式化的字符串,类似于 C 语言中的 printf,
// 变量引用都printf样式格式说明符,如%d,%i,%f 等,
// 这里$name%s 打印 String 变量 James 和$height%2.2f 打印浮点值 1.90
println(f"name:$name%s,name1:$name1%s,floatnum:$floatnum%1.2f")
// 's'允许在处理字符串时直接使用变量,在 println语句中将 String 变量($name)附加到普通字符串中。
println(s"name:$name,name1:$name1,floatnum:$floatnum")
// 字符串插入器可以处理具有任意表达式(${1 + 1})的字符串,任何表达式都可以嵌入到${}中。
println(s"name+name1:${name+name1},floatnum*2:${floatnum*2}")
// 条件控制语句 if(condition) 分支1 else 分支2
val i:Int = 12
if(i>10) println("大于10") else println("小于10")
// 条件表达式
val res1 = if(i>10) i else i*2
println(res1)
val res2 = if(i<10) i else "sdfadf" // 条件表达式 分支返回值不同,返回值类型为Any
println(res2)
val res3 = if(i<10) i // 条件表达式 没有else分支,返回值类型为AnyVal = ()
println(res3)
val score = 80
// {} 代码块
// if else if else 多条件条件控制语句
val res4 = {
if(score > 60 && score < 70) "及格"
else if(score >=70 && score < 80) "良好"
else "优秀" }
println(res4)
// 循环语句
val lines1 = List("hadoop hive spark scala","spark hive habase","hive spark java")
val array =Array(1,2,3,4,5,6)
// for 循环
for(e <- array) {
println(e)
}
for(e <- array) println(e)
// 角标循环
for(i <- 0 to 5) println(array(i))
// 0 to 5 含尾 until 不含尾
for(i <- 0 until 5) println(array(i))
for(i <- 0 to 5; j <- 0 to 5) println(i,j)
// yield 返回每次循环的值
val array1 = for(e <- array if e % 2 == 0) yield e
for(e <- array1) println(e)
println(array1)
// while 循环 while(condition){statement(s)}
var j = 0
while(j<5){
println(j)
j = j+1
}
// do while
do{
println(j)
j = j+1
}while(j<5)
// println(arry2)
}
// 方法定义:def methodname([list of parameters]): return type = {method}
def add(a:Int,b:Int): Int = {a+b}
def sayHello=println("Hello") // 无参数,不带()方法, 使用sayHello调用,使用sayHello()调用报错:unit does not take parameters
def sayHello1()=println("Hello too"); // 五参数列表返回值也为unit,但是可以使用sayHello sayHello() 调用,效果一致.
// 方法返回值: 无需return ,方法体最后一行为有值类型,则默认返回该值,时无值类型则返回 ()
def methodRet(a:Int)={
a
a*a
println(a*a)
}
// 方法转 函数 method _
val addf =add _
// println(addf(1,2))
// 函数定义: val f1 = (参数类型列表) => 方法体
val f1 = (x: Int) => x*x
// println(f1(2))
// 函数定义方法二 val f2:(Int,Int) => Int = (x,y) => x*y
// 参数类型 返回类型 参数列表 函数体
val f2:(Int,Int) => Int = (x,y) => x*y
// println(f2(3,5)
// 传名调用 / 传值调用
val fxx = (x:Int,y:Int) => x*y
//val fxx = (a: Int, b: Int) => a + b
def add3(f:(Int,Int) => Int, a:Int, b:Int) = {f(a,b)}
// def add2(f:(Int, Int) => Int, a: Int, b: Int) = {
// f(a, b) // f(1, 2) => 1 + 2
// }
def add2Test() = {
// 传值调用,
val res = add(add(1, 1), 1)
println(res)
// 传名调用, 方法/函数 作为参数 在新的方法/函数中调用,调用方法而不是值
val res1 = add3(fxx,2,3)
println(res1)
}
def methodTest(): Unit ={
println(s"add(1,2) => ${add(1,2)}")
sayHello
//sayHello() 报错
sayHello1
sayHello1()
println(s"addf(1,2) => ${addf(1,2)}")
println(s"f1(2) => ${f1(2)}")
println(s"f2(3,5) => ${f2(3,5)}")
val res = methodRet(5)
println(s"res=$res")
}
// map 集合映射方法简单使用
def mapTest(): Unit ={
val array = Array(1, 2, 3, 4, 5)
val arr1 = array.map((a:Int) => a*a)
println(arr1.toBuffer)
for(e <- arr1) println(e)
// 以下方法结果一致 ‘ _ ’ 相当于集合每个元素
val arr2 = array.map(x =>f1(x))
val arr3 = array.map(f1(_))
println(arr2.toBuffer, arr3.toBuffer)
}
def main(args: Array[String]): Unit = {
// 基础数据类型
test1()
// 方法 / 函数
methodTest()
add2Test()
mapTest()
}
}
2.复杂函数
import java.util.Date
object ComplexFunction {
val array = Array(1,2,3,4,5)
// 可变参数方法
def varFun(nums:Int*): Int ={
var sum = 0
for(e <- nums){sum += e}
sum
}
def varFun1(sum:Int,nums:Int*): Int ={
var sum1 = sum
for(e <- nums){sum1 += e}
sum1
}
def varAnyFun(paramters:Any*): Unit ={
}
def varparamFun(): Unit ={
var sum = varFun(1,2,3)
println(s"sum = $sum")
var sum1 = varFun1(10,1,2,3)
println(s"sum1 = $sum1")
}
// 默认参数
def defaultParamFun(a:Int=1,b:Int=1): Int ={a+b}
def defaultPfun(): Unit ={
println(s"defaultParamFun() = ${defaultParamFun()}")
println(s"defaultParamFun(5) = ${defaultParamFun(5)}")
println(s"defaultParamFun(5,6) = ${defaultParamFun(5,6)}")
println(s"defaultParamFun(b=6) = ${defaultParamFun(b=6)}")
}
// 高阶函数 将其他函数作为参数或其结果是函数的函数
def apply(f: Int => String, v: Int) = f(v)
// 定义一个方法, 参数为一个整型参数, 返回值为 String
def layout(x: Int) = "[" + x.toString() + "]"
def hightLevelFun(): Unit ={
println(apply(layout, 10))
}
// 部分参数应用函数
def log(date:Date,str:String): Unit ={println(date+str)}
val date = new Date
val logBoundDate:(String)=>Unit=log(date,_:String)
// 柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新 的函数返回一个以原有第二个参数为参数的函数。
def addcur(x:Int)(y:Int) = x + y
// 相当于一个高阶函数 addcur1(x: Int) 返回一个函数 (y: Int) => x + y
def addcur1(x: Int) = (y: Int) => x + y
def curfun(): Unit ={
println(s"addcur(2)(3) = ${addcur(2)(3)}")
}
// 偏函数 macth case
def func1:PartialFunction[String,Int]={
case "one" => 1
case "two" => 2
case _ => -1
}
// func1 func2 效果一致
def func2(num: String) : Int = num match { case "one" => 1 case "two" => 2 case _ => -1 }
// 类型匹配
def func3:PartialFunction[Any,Int]={case i:Int => i*10}
def partialfunTest(): Unit ={
println(s"func1('one') = ${func1("one")},func2('one') = ${func2("one")}")
val arr = Array(1,2,4,"sdfasd")
val arr1 = arr.collect(func3)
println(s"arr.collect(func3) = ${arr1.toBuffer}")
val arry = Array(1,2,3,4)
// map映射的几种写法
val arr2 = arry.map((x:Int)=> x*10) // 普通函数
println(s"arry.map((x:Int)=> x*10) = ${arr2.toBuffer}")
val arr3 = arry.map(_*10) // _ 表示遍历每个元素
println(s"arry.map(_*10) = ${arr3.toBuffer}")
val arr4 = arry.map {case x:Any => x*10} // case macth代码块
println(s"arry.map {case x:Any => x*10} = ${arr4.toBuffer}")
// val arr5 = arr.map {case x:Int => x*10} // 会报错
// println(s"arr5 = arr.map {case x:Int => x*10} = ${arr5.toBuffer}")
}
def main(args: Array[String]): Unit = {
// varparamFun()
// defaultPfun()
// hightLevelFun()
// logBoundDate("dfasdfas")
// curfun()
partialfunTest()
}
}
3.集合常用操作
import scala.collection.immutable
import scala.collection.mutable
object SetOpt {
/**
* 集合操作
* Scala 的集合有三大类:序列 Seq(List())、集 Set、映射 Map
* 所有的集合都扩展自 Iterable 特质,
* 在 Scala 中集合有可变(mutable)和不可变(immutable)两种类型
* immutable 类型的集合 初始化后就不能改变了
*
* 与 val 修饰的变量进行区别:
* val 变量不可变,指内存地址 不可被覆盖, 但是val 申明的 可变集合,仍然可以修改长度和元素(内存地址不变)
* 而 var变量,可以通过复制修改(覆盖原有)变量的内存地址
* 不可变集合 是指创建的集合 本身长度和元素都不可变
*/
def arrayTest(): Unit = {
// 初始化一个长度为 8 的定长数组,其所有元素均为 0
// 定长数组Array,不可修改长度,但可修改元素值
val array = new Array[Int](8)
// 直接打印定长数组,内容为数组的 hashcode 值
// println(array)
// 将数组转换成数组缓冲,就可以看到原数组中的内容了,toBuffer 会将数组转换长数组缓冲
println(s"array.toBuffer = ${array.toBuffer}")
//变长数组(数组缓冲)使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包
val arrB = mutable.ArrayBuffer[Int](-1,0)
println(s"arrB = ${arrB}")
// 以下操作,修改的时原数组,且没有返回值
arrB += 1 // 添加一个元素
println(s"arrB += 1 = ${arrB}")
arrB += (2,3,4) // 添加多个元素
println(s"arrB += (2,3,4) = ${arrB}")
arrB ++= Array(5,6,7) // 添加一个定长数组 ++=
println(s"arrB ++= Array(5,6,7) = ${arrB}")
arrB ++= mutable.ArrayBuffer(8,9) // 添加一个可变数组 ++=
println(s"arrB ++= ArrayBuffer(8,9) = ${arrB}")
arrB.insert(0,-3,-2) // 指定位置插入值
println(s"arrB.insert(0,-3,-2) = ${arrB}")
arrB.remove(0,2) // 删除指定位置的n个元素, 没有第二个参数, 就是删除一个元素
println(s"arrB.remove(0,2) = ${arrB}")
}
/**
* Seq 序列
* 不可变的序列 import scala.collection.immutable._
* 可变的序列 import scala.collection.mutable._
* 在 Scala 中列表要么为空(Nil 表示空列表)要么是一个 head 元素加上一个 tail 列表。
*/
def listTest(): Unit ={
/**
* 不可变List scala.collection.immutable.List
*/
// :: 操作符是将给定的头和尾创建一个新的列表 // 返回一个新List List[Int] = List(9, 5, 2)
println(s"9 :: List(5, 2) = ${9 :: List(5, 2)}")
var list = List(1,2,3)
// List前 插入元素生成新 List
println(s"0 :: list 返回新List ${0 :: list}")
println(s"list.::(0) 返回新List ${list.::(0)}")
println(s"0 +: list 返回新List ${0 +: list}")
println(s"list.+:(0) 返回新List ${list.+:(0)}")
// seq 的 head tail
println(s"list.head = ${list.head} list.tail = ${list.tail}")
// List后 插入元素生成新List (+ 号在前,则前面插入,+ 号在后,则后面插入)
println(s"list :+ 4 返回新List ${list :+ 4}")
println(s"list.:+(4) 返回新List ${list.:+(4)}")
val list1 = List(4,5,6)
//将 2 个 list 合并成一个新的 List
println(s"list ++ list1 合并2个list返回 ${list ++ list1}")
//将 list 插入到 list1 前面生成一个新的集合
println(s"list ++: list1 list 插入到list1前面 ${ list ++: list1}")
//将 list1 插入到 list 前面生成一个新的集合
println(s"list.:::(list1) list1插入到list前面 ${ list.:::(list1)}")
// :: 操作符是右结合的,如 9 :: 5 :: 2 :: Nil 相当于 9 :: (5 :: (2 :: Nil))
// Nil 空List immutable.Nil.type = List()
println(s" 9 :: 5 :: 2 :: Nil = ${ 9 :: 5 :: 2 :: Nil}")
println(s" 9 :: (5 :: (2 :: Nil) = ${9 :: (5 :: (2 :: Nil))}")
/**
* 可变List scala.collection.mutable.ListBuffer
*/
val lsB = mutable.ListBuffer[Int](3,4,5,6)
val lsB1 = new mutable.ListBuffer[Int]
println(s"lsB = ${lsB},lsB1 = ${lsB1}")
// 向 lst1 中追加元素,注意:没有生成新的集合
lsB1 += 0
println(s"lsB1 += 0 lsB1 = ${lsB1}")
lsB1.append(1)
println(s"lsB1.append(1) lsB1 = ${lsB1}")
//将 lsB1 中的元素追加到lsB中,注意:没有生成新的集合
lsB ++= lsB1
println(s"lsB ++= lsB1 lsB1 = ${lsB ++= lsB1}")
//将 lsB 和 lsB1 合并成一个新的 ListBuffer 注意:生成了一个集合
println(s"lsB ++ lsB1 = ${lsB ++ lsB1}")
//将元素追加到 lst0 的后面生成一个新的集合
println(s"lsB1 :+ 5 = ${lsB1 :+ 5}")
// 前插入并生成新list
println(s"5 +: lsB1 = ${5 +: lsB1}")
// lsB1前插入lsB
println(s"lsB1 ++: lsB = ${lsB1 ++: lsB}")
}
def setTest(): Unit ={
/**
* set中元素不能重复 ( 数据类型中的Map(),Set() 默认使用的时immutable的Map,Set)
* set集合中元素时无序的
* val Map : scala.collection.immutable.Map.type = { /* compiled code */ }
* val Set : scala.collection.immutable.Set.type = { /* compiled code */ }
* 不可变set
*/
val hashSet = immutable.HashSet[Int]()
// 追加元素并返回新 不可变set
val haset = hashSet + 0
println(s"hashSet + 0 = ${hashSet + 0}")
// 合并2个set返回新 不可变set
val haset1 = haset ++ Set(1,2,3)
println(s"haset ++ Set(1,2,3) = ${haset1}")
/**
* 可变set
*/
val mhset = mutable.HashSet[Int]()
mhset += 0
println(s"mhset += 0 mhset = ${mhset}")
mhset.add(1) // 等价 +=
println(s"mhset.add(1) mhset = ${mhset}")
mhset ++= Set(1,2,3,4) // 合并集合,去重
println(s"mhset ++= Set(1,2,3,4) mhset = ${mhset}")
mhset -= 0 // 去掉值为0 的元素
println(s"mhset -= 0 mhset = ${mhset}")
mhset.remove(1) // 等价 -=
println(s"mhset.remove(1) mhset = ${mhset}")
val setList =mhset.toList
println(s"mhset.toList setList = ${setList}")
val setArray =mhset.toArray
println(s"mhset.toArray setArray = ${setArray}")
var setBuf = mhset.toBuffer
println(s"mhset.toBuffer setBuf = ${setBuf}")
}
/**
* Map 也有2种,但是可变HashMap 更常用,默认Map() 类型即为可变 HashMap()
*/
def mapTest(): Unit ={
val map = new mutable.HashMap[String,Int]()
// 向 map种添加元素
map("Hadoop") = 1
map += (("Spark",2))
map.put("Hive",3)
println(map)
// 取值
val mapv = map.get("Spark")
println(s"map.get('Spark') ${mapv}")
val mapv1 = map.getOrElse("sdfa",0)
println(s"map.getOrElse('sdfa',0) ${mapv1}")
// 删除元素
map -= "Hive"
map.remove("Spark")
println(s"map -= 'Hive' map.remove('Spark') ${map}")
}
/**
* 元组可以容纳不同类型的对象,但它们也是不可变的
*/
def tupleTest(): Unit ={
var t = (1, "hello", true)
// 或者 Tuple3 为3元素固定tuple 因参数限制 tuple 最多有22个元素
val tuple3 = new Tuple3(1, "hello", true)
// 访问 tuple 中的元素
println(t._2) // 访问元组总的第二个元素
// 迭代元组
t.productIterator.foreach(println)
// 对偶元组
val tuple2 = (1, 3)
// 交换元组的元素位置, tuple2 没有变化, 生成了新的元组
val swap = tuple2.swap
println(swap)
}
/**
* Option 子类 Some None
* Map 集合 返回类型为 Option
*/
def optionTest(): Unit ={
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")
val value2: Option[String] = myMap.get("key2")
println(value1) // Some("value1")
println(value2) // None
println(value1.get) // "value"
}
/**
* 集合通用常用方法
* map, flatten, flatMap, filter, sorted, sortBy, sortWith, grouped, fold(折叠), foldLeft, foldRight,
* reduce, reduceLeft, aggregate, union, intersect(交集), diff(差集), head, tail, zip, mkString,
* foreach, length, slice, sum
*/
def setCommonMethod(): Unit ={
//创建一个 List
val lst0 = List(1,7,9,8,0,3,5,4,6,2)
val lst00 = List(0,0,1,1,2,2,3,3)
val lst01 = List(1,7,9,8,0,3,5,4,6,2)
val lst02 = List("Hadoop","Hive","Spark","Scala")
val lst04 = List("Hadoop Hive Spark Scala","Hive Scala","Spark Hadoop","Scala Spark Spark")
val lst05 = List(5,6,7)
val lst06 = List(5,6,7,8,9)
val arr = List(List(1, 2, 3), List(3, 4, 5), List(2), List(0))
println(s"lst0.toBuffer = ${lst0.toBuffer}")
// 集合大小:
println(s"lst0.size : ${lst0.size} lst0.length : ${lst0.length}")
// 集合head,tail, last, init(出最后一个外所有元素)
println(s"lst0.head : ${lst0.head} lst0.tail : ${lst0.tail} lst0.last : ${lst0.last} lst0.init : ${lst0.init}")
// 某元素下标
println(s"lst0.indexOf(0) : ${lst0.indexOf(0)}")
// 获取角标范围
println(s"lst0.indexOf(0) : ${lst0.indices} ${lst0.indices.toBuffer}")
// min max sum
println(s"lst0.min : ${lst0.min} lst0.max : ${lst0.max} lst0.sum : ${lst0.sum}")
// toString
println(s"lst0.toString : ${lst0.toString}")
// mkString
println("lst0.mkString(\" | \")" + s" ${lst0.mkString(" | ")}")
// toArray
println(s"lst0.toArray.toBuffer : ${lst0.toArray.toBuffer}")
// toSeq
println(s"lst0.toSeq : ${lst0.toSeq}")
// toSet 自动去重
println(s"lst00.toSet.toBuffer : ${lst00.toSet.toBuffer}")
// .map() list 转成元组 list
val lst000= lst02.map(x=>{(x,x.length)})
println(s"lst02.map(x=>{(x,x.length)} ${lst000}")
// toMap 元组list 转Map
println(s"lst03.toMap ${lst000.toMap}")
// 翻转 返回新list
println(s"lst0.reverse.toBuffer = ${lst0.reverse.toBuffer}")
// 包含与否:
println(s"lst0.contains(8) = ${lst0.contains(8)}")
// 是否为空:
println(s"lst0.isEmpty = ${lst0.isEmpty}")
// 去重
println(s"lst00.distinct.toBuffer = ${lst00.distinct.toBuffer}")
// 丢弃前n个元素 返回新list
println(s"lst0.drop(2).toBuffer = ${lst0.drop(2).toBuffer}")
// 丢弃后n个元素 返回新list
println(s"lst0.dropRight(2).toBuffer = ${lst0.dropRight(2).toBuffer}")
// 左 -> 右 丢弃元素 直到条件不符合 返回新list
println(s"lst0.dropWhile(x => x>5).toBuffer = ${lst0.dropWhile(x => x>5).toBuffer}")
// 是否已指定序列 Seq结尾 endsWith
println(s"lst0.endsWith(List(2)) = ${lst0.endsWith(List(2))}")
// 检测列表在指定位置是否包含指定序列
println(s"lst0.startsWith(List(1),0) ${lst0.startsWith(List(1),0)}")
// 切片截取 下标含头不含尾
println(s"${lst0.slice(0,5)}")
// 是否相等
println(s"lst0.equals(lst00) : ${lst0.equals(lst00)} lst0.equals(lst01) : ${lst0.equals(lst01)}")
// 交集
println(s"lst0.intersect(lst00).toBuffer : ${lst0.intersect(lst00).toBuffer}")
// 是否存在符合条件元素
println(s"lst0.exists(x => x>8) :${lst0.exists(x => x>8)}")
// 筛选符合条件元素返回新list
println(s"lst02.filter(x => x.length>5) : ${lst02.filter(x => x.length>5)}")
// 统计符合条件的所有元素
println(s"lst0.count(x => x>4) :${lst0.count(x => x>4)}")
// check all item
println("lst02.forall(x => x.startsWith(\"H\"))" + s" : ${lst02.forall(x => x.startsWith("H"))}")
// 将函数应用到列表的所有元素
lst02.foreach(x => println(s"lst02.foreach() :$x"))
// 扁平化: 将容器内的元素拆分形成一整个容器
println(s"lst02.flatten : ${lst02.flatten}")
// faltMap 先Map 再 扁平化
val lst100 = lst04.flatMap(_.split(" "))
println("lst04.flatMap(_.split(\" \"))" + s" : ${lst100}")
// grouped(Int) Int 个数据合并为一个子 list
println(s"lst100.grouped(2).toBuffer : ${lst100.grouped(2).toBuffer}")
// groupBy(key) lst100.groupBy(x => x) => Map()
val map100 = lst100.groupBy(x => x)
println(s"lst100.groupBy(x => x) : ${map100}")
// mapValues[W](f : scala.Function1[V, W]) : scala.collection.immutable.Map[K, W] = {}
// mapValues 只对 原Map() 的values 实现函数操作,并返回 原K,和新v W 的Map()
val map101 = map100.mapValues(_.length)
println(s"map100.mapValues(_.length) : ${map101}")
// reduce 聚合
println(s"lst0.reduce(_+_) : ${lst0.reduce(_+_)}")
// 排序
println(s"lst0.sorted.toBuffer 默认排序 : ${lst0.sorted.toBuffer}")
println(s"lst0.sortBy(x => x) : ${lst0.sortBy(x => x)}")
println(s"map101.toList.sortBy(x => - x._2) : ${map101.toList.sortBy(x => - x._2)}")
// zip 2个集合匹配成新的List
println(s"lst02.zipWithIndex : ${lst02.zipWithIndex}")
println(s"lst02.zip(lst05) : ${lst02.zip(lst05)}")
println(s"lst02.zip(lst06) : ${lst02.zip(lst06)}")
//折叠:有初始值(无特定顺序) par 并行计算
val lst11 = lst0.par.fold(0)((x, y) => x + y)
println(s"并行折叠:lst0.par.fold(0)((x, y) => x + y) : ${lst11}")
//lst0.par.foreach(println(_))
val lst1 = lst0.par.map(_*10)
println(lst1.toBuffer)
//折叠:有初始值(有特定顺序)
val lst12 = lst0.foldLeft(0)((x, y) => x + y)
println(lst12)
//聚合
/**
* aggregate[B](z : => B)(seqop : scala.Function2[B, A, B], combop : scala.Function2[B, B, B]) : B = {}
* aggregate 聚合函数 需要3个参数;
* z 是聚合初始值
* seqop 分区聚合函数 该函数的 第一个 _ 是初始值 z 第二个 _ 相当于该分区 运算逻辑是:0 —> 遍历所有分区
* combop 组合集合函数 该函数的 第一个 _ 是初始值 z 第二个 _ seqop的返回结果 运算逻辑是:0 —> 遍历所有分区结果
*/
val result = arr.aggregate(0)(_+_.sum, _+_)
println(result)
/**
val words: RDD[String] = data.flatMap(_.split(" "))
val countsMap=words.aggregate(mutable.HashMap[String,Int]())((agg:mutable.HashMap[String,Int], word)=>{
if(!agg.contains(word)){
agg.put(word,1)
}else{
agg.put(word,agg(word)+1)
}
agg
},(agg1:mutable.HashMap[String,Int],agg2:mutable.HashMap[String,Int])=> {
for((word,count)<-agg1){
if(!agg2.contains(word)){
agg2.put(word,1)
}else{
agg2.put(word,agg2(word)+count)
}
}
agg2
}
)
println(countsMap.toList)
*/
}
def main(args: Array[String]): Unit = {
// arrayTest()
// listTest()
// setTest()
// mapTest()
// tupleTest()
setCommonMethod()
// optionTest()
}
}
其他复杂操作:
1.scala 单例对象Object
2.scala 类,柱构造器,辅助构造器
3.scala伴生类,apply
4.scala trait 特质,相当于Java的接口,但更强大
5.抽象类 abstract class
6.样例类/样例对象 case class
7.匹配模式 match case
8.并发编程模型 Akka
9.其他高级语法:
1)隐式(implicit)
2)泛型
3)类型约束