------------- scala简介 ----------------
官网:https://www.scala-lang.org/
Scala语言很强大,集成了面向对象和函数式编程的特点。
运行在JVM(jdk)。
大数据中为什么学习scala?
spark是scala语言编写。
python写spark 挺好的
java写spark 很糟糕(代码实在是太多了)
scala写spark 很完美
------------ scala特点----------------
1)优雅
框架设计中第一个要考虑的问题就是API是否优雅。
精简的封装。
代码精简(少)。
2)速度快
scala语言表达能力强。
一行代码=多行java代码,开发速度快。
3)完美融合hadoop生态
scala是静态编译,表达能力强并且代码量少。
--------------安装Scala----------------
1)下载
2)解压
3)配置环境变量
SCALA_HOME=
path
------------IDEA配置----------------
1)File->Settings->Plugins->安装Scala插件
2)File->Project Stucture ->Global Libraries -> + ->Scala SDK
------------Scala基础语法----------------
1)Scala程序的开始
helloworld
2)Scala的数据类型
Scala与java一样,有8中数值类型:
Byte/Char/Short/Int/Long/Float/Double/Boolean/
和Unit类型(void)
注意:scala中无包装类型。
3)Scala定义变量
两个关键字:val var
val:定义变量值不可变
var:定义的变量值是可变的
scala编译器会自动的推断类型!
指定类型: val str:String = “hunterhenshuai”
注意:类型要保持一致
Unit = ():()相当于什么都没有用()表示。
4)条件表达式
if:判断
val y = if(x>0) 1 else 2
val k = if(x<0) 0 else if(x>=1) 1 else -1
if和else if:多个条件的判断,符合条件看左侧,不符合条件看右侧
var b = if(x>0) 1
b: AnyVal = ()
b: AnyVal = true
if后面没有else的话,b默认的是Anyval类型,不满足if,就是Anyval = ()
如果给c指定类型,这里还只能从下面这三种来选
Any:包含Anyval和AnyRef
Anyval:包含scala所有类型
AnyRef:Scala classes与Java Classes
Any相当于java的Object
5)块表达式
在scala中{}包含一系列表达式,块中的最后一个表达式的值就是块的值
6)循环
1 to 5 : 生成1到5
Range(1,2,3,4,5)
for(i <- 1 to 5) print(i)
12345
for(i< 1 to 5; j< 1 to 5) print(i,j)
yield:生成一个新的集合关键字
for(i <- 1 to 5) yield i
Vector(1, 2, 3, 4, 5)
1.to(10).map(_*1000)
map:取出元素
_:代表前面用to生成的元祖
7)方法定义
Scala中 + - * / % 的作用和Java一样,但是特别的是,这些操作符实际上是方法。
1 to 10
1.to(10)
def m1(a:Int,b:Int):Int = {
a + b
}
def:定义方法的关键字
m1:方法名
a:参数列表
b:参数列表
Int:返回值类型
a + b:函数体
---------函数-----------
1)方式1
方法转换为函数
方式:方法名 _
res6: (Int, Int) => Int =
代表一个函数,并且有两个参数。
(Int, Int)
代表参数列表
Int
代表返回值类型
=>
代表函数
2)方式2
定义函数:
val h1 = (a:Int,b:Int) => {a * b}
h1:函数名
(a:Int,b:Int):函数的参数类型
{a * b}:函数体
这个方式定义的函数,如果用小括号,例如(a * 1,b * 1)就是返回一个元组,返回类型为(Int,Int)
如果是{a1;b1}这样的,只返回b*1的结果,返回类型为Int
------------传值调用&传名调用-------------
函数式编程:方法的参数可以是一个函数
传值调用:
1.先计算balance的值
2.把这个值作为参数传递给printa
object test {
var a = 1000
def eat():Unit = {
a = a -50
}
def balance():Int = {
eat()
a
}
//这里是Int型的参数x
def printa(x:Int):Unit = {
for (a<-1 to 5)
println(f"为:$x")
}
def main(args: Array[String]): Unit = {
printa(balance())
}
}
传名调用:传递的是函数
将balance方法的名称传递到方法内部执行
object test {
var a = 1000
def eat():Unit = {
a = a -50
}
def balance():Int = {
eat()
a
}
//这里x:=>Int 是 类型为Int型的函数x
def printa(x: =>Int):Unit = {
for (a<-1 to 5)
println(f"为:$x")
}
def main(args: Array[String]): Unit = {
printa(balance())
}
}
-------------可变参数函数---------------
java中的可变参数:public static void m1(String …arg){}
scala中的可变参数:def sum(ints:Int*): Int ={}
加了通配符*
--------------默认参数值函数--------------
如果传递了参数,则使用传递的值。如果不传递参数,则使用默认值。
scala>def b(x:Int = 3):Unit = {print(x)}
scala>b()
3
----------------高阶函数--------------------
定义:将其他函数作为参数,或者其结果是函数的函数。
object test02 {
def getPerson(h:Int => String,f:Int):String = {
h(f)
}
def Person(x:Int):String = "I am " + x + "岁"
def main(args: Array[String]): Unit = {
print(getPerson(Person,18))
}
}
---------------部分参数应用函数----------------
如果函数传递所有预期的函数,则表示完全应用它了。
如果只传递几个参数,并不是全部参数,那么将返回部分应用的函数。
scala> def c(x:Int,y:Int):Int = {x+y}
c: (x: Int, y: Int)Int
scala> c(1,_:Int)
res10: Int => Int = <function1>
scala> res10(2)
res12: Int = 3
scala> val b = c(1,_:Int)
b: Int => Int = <function1>
scala> b(2)
res13: Int = 3
scala> b(3)
res14: Int = 4
-------------字符串的格式化输出---------------
文字插值器:f/s
scala> val name="ycf"
name: String = ycf
scala> val age = 18
age: Int = 18
scala> println(f"name=$name age=$age")
name=ycf age=18
scala> print(s"1+1 = ${1+1}")
1+1 = 2
scala> print(f"1+1 = ${1+1}")
1+1 = 2
---------------柯理化-------------------
指的是将原来接收的两个参数的函数变为一个新的接收一个参数的函数,这样的一个过程。
函数的通用性降低,但是适用性提高
scala> def c(x:Int)(y:Int) = {x+y}
c: (x: Int)(y: Int)Int
scala> c(1)(2)
res23: Int = 3
-----------------偏函数-------------------
被包在花括号内没有match的一组case语句的是一个偏函数。
PartialFunction[A,B]
A:参数类型
B:返回类型
常用与模式匹配。
object test extends App {
def b(str:String) = {
if ("ycf".equals(str)) 18 else 0
}
def c:PartialFunction[String,Int] = {
case "ycf" => 18
case _ => 0
}
println(b("ycf"))
println(b("Ycf"))
println(c("ycf"))
println(c("Ycf"))
}
18
0
18
0
-----------------scala数组----------------------
数组定义1: var arr = new Array[String](3)
String:存储的元素类型
3:存储3个元素
添加元素: arr(1) = "hunter"
数组定义2: val arr1 = Array[Int](1,2,3,4,5,6)
改变内容:arr1(1) = 18
添加元素:arr1 += 22 长度不可以改变
--------------数组方法--------------------------
-》map(映射)
映射: 2 4 6
映射关系:f(x) = x*5
对应映射关系:10 20 30
scala> val arr = Array[Int](1,2,3,4)
arr: Array[Int] = Array(1, 2, 3, 4)
scala> arr.map((x:Int)=>{x*10})
res45: Array[Int] = Array(10, 20, 30, 40)
-》flatten
扁平化操作
scala> val arr = Array[String]( "hello ycf " ,"hello hunter")
arr: Array[String] = Array("hello ycf ", hello hunter)
scala> arr.map(_.split(" "))
res48: Array[Array[String]] = Array(Array(hello, ycf), Array(hello, hunter))
scala> arr.map(_.split(" ")).flatten
res49: Array[String] = Array(hello, ycf, hello, hunter)
-》flatMap
相当于先map操作再flatten
scala> val arr = Array[String]( "hello ycf " ,"hello hunter")
arr: Array[String] = Array("hello ycf ", hello hunter)
scala> arr.flatMap(_.split(" "))
res51: Array[String] = Array(hello, ycf, hello, hunter)
-》foreach
遍历数组中的元素
scala> res51.foreach((x:String) => {println(x)})
hello
ycf
hello
hunter
-》GroupBy
分组
WordCount程序
x._1 key
x._2 value
scala> val arr = Array[String]( "hello ycf " ,"hello hunter")
scala> arr.flatMap(_.split(" ")).groupBy(x => x).map(x => (x._1,x._2.length))
res79: scala.collection.immutable.Map[String,Int] = Map(ycf -> 1, hunter -> 1, hello -> 2)
-》sortBy
排序
scala> arr.flatMap(_.split(" ")).groupBy(x => x).map(x => (x._1,x._2.length)).toList.sortBy(x => x._2)
res82: List[(String, Int)] = List((ycf,1), (hunter,1), (hello,2))
scala> arr.flatMap(_.split(" ")).groupBy(x => x).map(x => (x._1,x._2.length)).toList.sortBy(x => -(x._2))
res83: List[(String, Int)] = List((hello,2), (ycf,1), (hunter,1))
元组()这种类型的取值参考元组