一、scala概述
Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言 、并集成面向对象编程和函数式编程的各种特性。
scala与java一样,运行在JVM。
二、scala安装部署
解压、设置环境变量
三、scala文件的编译运行
scalac hello.scala
scala hello
注:
- 比如说要改生产上spark的代码,用这种方式只要修改一个或多个之后,编译scala文件,替换原文件即可。
- scalac 生成的也是class文件
四、定义变量和值
变量var
值val :不可修改,如果修改的话会报错 error:reassginment to val
如何定义?
//完整定义
val/var 名称:类型 = ???
//省略定义
val/var 名称 = ??? //可以不显式的指定变量的类型,scala能够进行类型推导
val 定义 immutable variable 不可变
var 定义 mytable variable 可变
lazy val 定义惰性求值的常量
什么时候用到lazy val?
如果定义的变量在后续的程序可能不会被用到,那么可以定义为lazy val,只有在第一次被使用的时候,才会求值。
五、常用的数据类型
Int/Long/Double/Float
boolean 不建议用,用0跟1 代替
六、类型转换
//强制类型转换
val money = 10.asInstanceOf[Double]
Double = 10.0
//判断类型
val aa = 10,00
aa.isInstanceOf[Double]
Boolean = true
七、scala函数的定义
//参数 //返回值
def 函数名(x:Int,y:String): Unit ={
xxxxx //最后一行代表函数的返回值
}
返回值哪里也可以不写,scala有类型推导
注:
当调用的函数没有入参时,可以直接调用,省略括号(有一种情况除外)
八、条件表达式
- if else
val a = if( x > 10 ) print("aaa") else print("bbb")
- to []
- until [)
- range[)
1 to 10 或 1.to(10)
res4: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1 until 10 或 1.until(10)
res0: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
Range(1,10)
scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
Range(1,10,2) //第三个参数叫做步长,也可以反着来
res10: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9)
scala> Range(10,1,-2) //如果为0,会报参数异常
res13: scala.collection.immutable.Range = Range(10, 8, 6, 4, 2)
- 循环
for( i <- 1 to 10 if i%2 == 0){
print(i)
}
- 默认参数
- 变长参数
- 命名参数
//默认参数
def defaultMethod(fileName:String = "/opt"): Unit ={
println(fileName)
}
defaultMethod("/var")//参数如果不填,就会用默认的参数,如果用了就是传的参数
defaultMethod()//括号必须带
//命名参数,了解即可
def mingMing(spark:String,linux:String): Unit ={
println(spark)
println(linux)
}
mingMing(linux="aaa",spark = "bbb")//顺序可以颠倒,类似insert into
//变长参数,跟java里可变参数差不多
def kebian(a:Int,b:Int,num:Int*): Int ={
var result = a+b
for(i <- num){
result += i
}
result
}
println(kebian(1,2,3,4))
println(kebian(1,2,1 to 10:_*))//因为1 to 10 是 range.Inclsive,用_*转换
kebian(Array("aa","bb"):_*)//数组也一样
九、面向对象
- 类的创建
class people{
//定义属性
var name:String = _ //_表示占位符
var age = 10
private[this] val gender:String = "M" //私有常量,外部不可访问
//定义方法
def eat(): Unit ={
println("这个叫"+this.name+"的人"+this.age+"岁了,他在吃饭")
}
}
//对象的创建
val people = new people
people.age = 11
people.name = "bob"
people.eat()
//主构造参数
//构造函数的参数和属性能够被直接使用(非private),属性需要变量或值定义
class animal( var name:String, val color:String ){
var age:Int = _
}
val cat = new animal("li","green")
cat.age = 10
println(cat.age+"="+cat.name+cat.color)
//附属构造参数
def this( name:String, color:String, varies:String){
this(name,color)
this.varies = varies
}
2.继承
extends
当继承的时候,子类先会调用父类的构造方法
3.重写
如果想调用父类的方法是需要用override,属性也一样
override def toString(){
}
4.抽象类
类中有多个方法、属性没有实现,只有定义,不能直接使用,只能通过子类的实现
abstract class
子类重写父类时,可以不适用override
5.case class
//case class 的用途,不用new 可以直接使用,模式匹配
def main(args: Array[String]): Unit = {
println(People("abc").name)
}
case class People(name :String)
6.trait
相当于一个借口,只用定义,没有实现
一个类要想实现trait,要使用关键字with
第一个类要使用extends,后面使用with
十、Class和Object的区别
- object
①.Object修饰的类不用new就能直接使用
②.Object类相当于静态类
Class&Object
相同的类,叫做伴生,Object是class的伴生对象,class是object的伴生类
/**
* 伴生类、对象
*
*/
class ApplyAPP{
def applyClass(): Unit ={
println("Class apply method")
}
def apply() ={
println("Object apply method")
new ApplyAPP() //返回值
}
}
object ApplyAPP {
println("Object come")
def apply() ={
println("Object apply method")
new ApplyAPP() //返回值
}
def static(): Unit ={
println("object static method")
}
println("Object leave")
}
object mainApp{
def main(args: Array[String]): Unit = {
//ApplyAPP.static() //object 不用new
val a = ApplyAPP() //调用Object
a.applyClass() //可以直接调用class中的方法,因为Object中Apply方法new Class() 类型调用
a() //先定义对象 val a = Object() 在用 a() 调用class的apply方法 变量调用
}
}
十一、集合
重点掌握:
①.如何创建
②.如何赋值
③.如何取值
- 数组
/**
* 数组
*/
//定长
val arr = new Array[String](5)
//互为伴生对象,必然调用的Object中的apply方法,apply方法new array class
val arr1 = Array("aaa","bbb","ccc")//可变参数
//取值 ,从0开始
println(arr1(1))
val intArr = Array(1,2,3,4,5,6)
println(intArr.min)
println(intArr.max)
println(intArr.sum)
println(intArr.mkString)//拼成字符串 调用下面的方法
println(intArr.mkString("\t"))//以什么分割 调用下面的方法
println(intArr.mkString("[",",","]"))//拼成以[开头,以]结尾
//变长 ArrayBuffer
import scala.collection.mutable.ArrayBuffer
val arr2 = ArrayBuffer[Int]() //创建
arr2 += 1 //赋值
arr2 += 2
arr2 += (3,4,5)
arr2 ++= Array(6,7,8,9) //边长加定长 ++=
println(arr2(7))
arr2.insert(0,5) //添加,从第几个索引插入
arr2.remove(0,3) //删除,从索引处删除3个元素
arr2.trimEnd(2) //从后面删除两个
arr2.toArray //边长变定长
//遍历
for(ele <- arr2){
println(ele)
}
- List
NIL就是一个空的List
/**
* List
*/
//定长
val list = List(1,2,3,4,5)
//list == head + tail
println(list.head) //获取第一个元素
println(list.tail) //获取除第一个元素之外的元素
// 头 尾
val list2 = 1 :: Nil //1
println(list2)
val list3 = 2 :: list2 //2,1
println(list3)
//变长
import scala.collection.mutable.ListBuffer
val list5 = ListBuffer[Int]()
//添加元素
list5 += 1
list5 += (2,3,4)
list5 ++= List(6,7,8)
println(list5)
//减少元素
list5 -= 1
list5 -= (1,2)
list5 --= List(5,6,7)
println(list5)
list5.toList //变长转定长
- SET
Set:
set:无序、不重复
list:有序,可重复
- Map
//创建,不可变的
val map = Map("ming"->30,"hong"->20)
//取值
println(map("ming"))
import scala.collection.mutable.HashMap
val hashmap = HashMap[String,Int]() //hashset 实现
hashmap("heiehi") = 20 //赋值
hashmap("bb") = 21
hashmap("bb") = 22 //修改
println(hashmap("bb"))
hashmap.get("cc") //如果没有也不报错
hashmap.getOrElse("cc",99) //生产常用
hashmap += ("aa" -> 2,"abc" ->2 )
//遍历
/* for((key,value) <- hashmap){
println(key+value)
}*/
/* for(key <- hashmap.keySet){
println(key+ hashmap(key))
}*/
for(value <- hashmap.values){
println(value)
}
-
Tuple
val ip = "192.168.10.100:8080"
val tuple: (String, String) = split(ip)
//取值
println(tuple._1+"====="+tuple._2)
def split(ip:String) ={
val strings = ip.split(":")
//返回tuple类型
(strings(0),strings(1))
}
十二、SCALA高阶函数☆☆☆☆☆
val l = List(1,2,3,4,5,6)
// y=f(x)=x*2
//Map:对集合的每一个元素都进行一个操作
//因为只有一个入参,括号可以省略
l.map(x => x*2)
//简写
//foreach(对每个元素进行一个操作)
l.map(_*2).foreach(println)
//filter过滤
l.map(_*2).filter(_ >= 10).foreach(println)
//take,取前几个
//println(l.take(3))
//reduce,对集合的元素,两两操作,与reduceleft功能相同
//println(l.reduce(_+_))
//reduceRight从右边开始
println(l.reduceRight(_-_))
val c = l.reduceRight((a,b)=>{
println(a+"===="+b)
a - b
})
//最终值加上一个10,fold(0)与reduce功能相同
println(l.fold(10)(_+_))
println(l.foldLeft(10)(_-_))
//先算10,然后从最后一位
val c = l.foldRight(10)((a,b)=>{
println(a+"====="+b)
a-b
})
//不管right还是left都是从10开始
val c = l.foldLeft(10)((a,b)=>{
println(a+"====="+b)
a-b
})
val l = List(1,2,3,4,5,6)
val s = List("a","b","c","d","e")
//zip:把两个集合压在一起,个数以最少的为基准
println(l.zip(s))
val l2 = List(List(1,2),List(3,4),List(5,6))
//将集合内的集合打扁
println(l2.flatten)
//打扁进行操作
l2.flatMap(_.map(_*2)).foreach(println)
十三、字符串操作
val a = "单行"
val b =
"""
|你好,
|臭傻逼
""".stripMargin//多行,""之后,再shift+"
println(b)
val c = "hello"
println(s"print+$c")//用变量的方式传递,字符串插值
十四、File&URL
//导入scala.io,传入文件路径及文件编码
val source: BufferedSource =
Source.fromFile("C:\\Users\\Administrator\\Desktop\\word.txt")(Codec.UTF8)
//读文件
for (line <- source.getLines()){
println(line)
}
//读url(重点)
//大数据平台常用这种方式获取数据
//一般用json,xml消耗略大,标签太多,要回头
def readApi(): Unit ={
val source1 = Source.fromURL("http://www.baidu.com")
for(line<-source1.getLines()){
println(line)
}
}
十五、Exception
try {
//val a = 1 / 0
var source:BufferedSource = Source.fromFile("C:\\Users\\Administrator\\Desktop\\word1121.txt")(Codec.UTF8)
} catch {
case e:FileNotFoundException => println("文件不存在")
case e:Exception => throw new RuntimeException("123")
case e:ArithmeticException => println("分母不能为0")
} finally {
println("finally")
}
十六、Match模式匹配
val array = Array("A","B","C")
val str = array(Random.nextInt(array.length))
str match{
case "A" => println(1)
case "B" => println(2)
case _ => println(3)
}
//模式匹配方法
def greet(array: Array[String]): Unit ={
array match {
case Array("A") => println("A")
case Array(x,y) => println(x+" "+y)
case Array("A",_*) => println("可变参数")
case _ => println("")
}
}
//模式匹配函数的另一种写法
def greet(array: Array[String]) = array match {
case Array("A") => println("A")
case Array(x,y) => println(x+" "+y)
case Array("A",_*) => println("可变参数")
case _ => println("")
}
//偏函数,被包含在花括号内,没有match的case语句
//PartialFunction[A,B],入参的类型,出参的类型
def greet2:PartialFunction[String,String] = {
case "A" => "A"
case x => x
case "C" => "可变参数"
case _ => ""
}
十七、隐式转换
能不用就不用。
JAVA中在一个类如何添加方法?
最简单的继承。
静态代理:持有对方的一个引用
动态代理:JDK(接口)、CGLIB(类)
在scala中是隐式转换。
作用:偷偷的做了什么。
import implicit._占个坑,sparkSQL会用到。
对阅读和维护不友好。
//定义隐式转换的格式
//implicit def XToY/X2Y(X:type):Y = new Y(X.attribute)
implicit def Dog2peopel(dog:Dog):people = new people(dog.name)