2019-09-18写Mac终端运行scala
mac命令行编译执行运行scala文件;Scala编译和运行
3.检验结果
在终端输入scala 命令,进入scala解释器,然后输入1+2
4.退出scala解释器。
输入 :q 或:quit
编译src下的scala:
scalac -classpath lib/spark-assembly-1.5.1-hadoop2.6.0.jar -d classes src/com/xzj/process/*
classes文件夹下面就会有相应的.class文件
scala -classpath classes:lib/spark-assembly-1.5.1-hadoop2.6.0.jar com.xzj.process.Main
➜ scala git:(master) ✗ cd /Users/tianzi/Desktop/时间复杂度/scala
➜ scala git:(master) ✗ scala s_name.scala
hello world
- scalac:scala的编译器
- -classpath:指明外部依赖包
- -d:指明 编译后的输出文件 要放到哪里,这里把编译结果放在classes文件下
- 最后指明需要编译的scala文件(该例子是整个目录)。
s_name.scala 文件
必须是双引号
println("hello world")
package com.xx.yy
import java.util._;
object HelloWorld {
def main(args: Array[String]) {
println("Hello World!");
}
}
项目的结构src
|--com
|--xzj
|--process
|--Main.scala
|--NAStatsCounter.scala
NAStatsCounter.scala内容
package com.xzj.process
import org.apache.spark.util.StatCounter
class NAStatsCounter extends Serializable {
val stats: StatCounter = new StatCounter()
var missing: Long = 0
def add(x: Double): NAStatsCounter = {
if (java.lang.Double.isNaN(x)) {
missing += 1
} else {
stats.merge(x)
}
this
}
def merge(other: NAStatsCounter): NAStatsCounter = {
stats.merge(other.stats)
missing += other.missing
this
}
override def toString = {
"stats: " + stats.toString + "NaN: " + missing
}
}
object NAStatsCounter extends Serializable {
def apply(x: Double) = new NAStatsCounter().add(x)
}
Main.scala内容
package com.xzj.process
object Main {
def main(args: Array[String]) {
var testArray = Array(11.1, 12.1, 13.2, Double.NaN)
var test2 = Array(11, 3, 22.1, Double.NaN, 0)
var testc = testArray.map(c => NAStatsCounter(c))
var testc2 = test2.map(NAStatsCounter(_))
var list = testc.zip(testc2)
list.map {
case (a, b) => a.merge(b)
}
list.foreach(println)
}
}
安装
首先,确保安装了Java 8 JDK。
要检查,请打开终端并键入:
java -version(确保您拥有1.8版本。)
(如果您没有安装它,请在此处下载Java。)
然后,安装Scala:
通过安装诸如IntelliJ的IDE或sbt,Scala的构建工具。
如果您熟悉命令行,则最好;下载SBT
在命令行上使用Scala和sbt入门
在命令行上使用sbt和ScalaTest测试Scala
各工具的版本
- Scala : 2.12.6
- Sbt : 1.1.6
- IDEA : 2018.1.4
- Atom : 1.23.2
➜ fibncci.github.io git:(master) brew -v
Homebrew 2.1.11
Homebrew/homebrew-core (git revision b669; last commit 2019-09-05)
➜ fibncci.github.io git:(master) brew info scala
scala: stable 2.13.0
JVM-based programming language
https://www.scala-lang.org/
Required: java >= 1.8 ✔
To use with IntelliJ, set the Scala home to: 目录
/usr/local/opt/scala/idea
build_error: 0 (30 days) 构建错误:0(30天)
➜ fibncci.github.io git:(master) brew install scala
使用homebrew安装scala sdk和可以构建scala应用的工具
Pruned 14 symbolic links and 1 directories from /usr/local
➜ fibncci.github.io git:(master) brew list
scala tree unrar
➜ fibncci.github.io git:(master) brew install sbt@1
==> Downloading https://github.com/sbt/sbt/releases/download/v1.3.0/sbt-1.3.0.tg
######################### 100.0%
curl: 卷曲 增删改查 CRUD(create, read, update, delete)
🍺 /usr/local/Cellar/sbt/1.3.0: 765 files, 54.9MB, built in 2 minutes 51 seconds
➜ ~ git:(master) ✗ cd /Users/tianzi/Documents/scala
cd到一个空的目录,运行如下命令创建一个模板工程
➜ scala git:(master) ✗ sbt new scala/hello-world.g8
[info] Set current project to scala (in build
name [Hello World template]:
# 直接回车,使用默认工程名即可
# 回车后多一个 hello-world-template ;
Template applied in /Users/tianzi/Documents/scala/./hello-world-template
2.cd到hello-world-template目录,并运行sbt命令,进入sbt的交互模式
➜ scala git:(master) ✗ cd hello-world-template
➜ hello-world-template git:(master) ✗ sbt
[info] [launcher] getting org.scala-sbt sbt 1.2.8 (this may take some time)...
...
[info] Running Main
Hello, World!
[success] Total time: 20 s, completed 2019-9-18 8:32:30
1. Waiting for source changes in project hello-world-template... (press enter to interrupt)
➜ hello-world-template git:(master) ✗ scala -version
Scala code runner version 2.13.0 -- Copyright 2002-2019, LAMP/EPFL and Lightbend, Inc.
➜ hello-world-template git:(master) ✗ scala
Welcome to Scala 2.13.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181).
Type in expressions for evaluation. Or try :help.
scala> 1+2
res0: Int = 3
笔记
Scala语言的名称来自于“可伸展的语言”。它是一种把面向对象和函数式编程理念加入到静态类型语言中的 混血儿。它跑在标准的 Java 平台上,可以与所有的 Java 库实现无缝 交互。它也是用来编写脚 把 Java 控件链在一起的很好的语言。但是用它来建立大系统 和可重用控件的架构将更能够发挥它的力量。
Scala介绍 ;Scala是基于JVM的一种编程语言 1.Scala的六大特征
-
Java和Scala可以无缝衔接
-
类型推测(自动推测类型)
-
并发和分布式(Actor)
-
特质(trait),特征(类似于java中interfaces和abstract结合)
-
模式匹配(类似于java中的switch)
-
高阶函数
1. Scala的安装
1.环境变量
1.官网下载scala:https://www.scala-lang.org/download/all.html
2.解压zip或双击msi包
查看版本号scala -version
2.开发环境
方法一:
1.下载scala插件(对应eclipse版本):http://scala-ide.org/download/prev-stable.html
2.解压zip,将features和plugins文件夹拷贝到eclipse安装目录下的dropins/scala。若没有该目录,自行创建
方法二:
西在Scala IDE:http://scala-ide.org/download/sdk.html
方法三:
1.安装IDEA
2.打开IDEA,点击Configure->Plugins,搜索Scala,点击Install安装
3.设置JDK,点击Configure->Project Defaults->Project Structure
4.创建Scala项目,点击Create New Project->Scala->Scala。
5.更改SDK版本号,点击Browse,选择本地安装的Scala目录,选择System
Scala基础
Byte
Char
Short
Int
Long
Float
Double
Boolean
这些都是类- String: 使用底层的
java.lang.String
表示字符串,但通过StringOps
类为字符串追加上百种操作
数据类型 | 描述 |
---|---|
Byte | 8bit的有符号数字 |
Short | 16 bit 有符号的数字 |
Int | 32 bit 有符号的数据 |
Long | 64 bit 有符号的数字 |
Float | 32 bit IEEE 754 单精度浮点数 |
Double | 64 bit IEEE 754 双精度浮点数 |
Char | 16 bit Unicode字符 |
String | 字符串 |
Boolean | 布尔类型 |
Unit | 表示无值,和其他语言中void等同 |
Null | 空值或者空引用。Trait,其唯一实例是null,是AnyRef的子类 |
Nothing | 所有其他类型的子类型,表示没有值。Trait,所有类型(包括AnyRef和AnyVal)的子类,没有实例 |
Any | 所有类型的超类,任何实例都属于Any类型 |
AnyRef | 所有引用类型的超类 |
AnyVal | 所有值类型的超类 |
None | Option的两个子类之一,另一个是Some,用于安全的函数返回值 |
Nil | 长度为0的List |
2.变量和常量的声明 定义常量或者变量的时候,也可以写上返回的类型,一般省略,如:val a;Int = 10
常量不可在赋值
/**
* 变量:用var定义,可修改
* 常量:用val定义,不可修改
* /
var age = 10
val name = "zhangsan"
3.类和对象 创建类
class Person{
val name = "zhangsan"
val age = 18
def sayName() = {
"my name is "+ name
}
创建对象
object Lesson_Class {
def main(args: Array[String]): Unit = {
val person = new Person()
println(person.age);
println(person.sayName())
}
}
伴生类和伴生对象
class Person(xname :String , xage :Int){
var name = Person.name
val age = xage
var gender = "m"
def this(name:String,age:Int,g:String){
this(name,age)
gender = g
}
def sayName() = {
"my name is "+ name
}
}
object Person {
val name = "zhangsanfeng"
def main(args: Array[String]): Unit = {
val person = new Person("wagnwu",10,"f")
println(person.age);
println(person.sayName())
println(person.gender)
}
}
如果在同一个文件中,object对象和class类的名称相同,则这个对象就是这个类的伴生对象,这个类就是这个对象的伴生类。可以互相访问私有变量
Apply方法
object ScalaDemo01 { def main(args: Array[String]): Unit = { val p = new Person(“zs”,19) val person = Person(“wagnwu”,10) } } class Person(xname :String , xage :Int){ val name = “zs” val age = xage var gender = “m” def this(name:String,age:Int,g:String){ this(name,age) gender = g } } object Person{ def apply(name:String,age:Int)={ new Person(name,age) } }
使用apply方法,实现对象时可以不用加new scala中object时单例对象,相当于java中的工具类,可以看成是定义静态的方法的类,object不可以传参数。另外,Trait不可以传参数 Scala中的class类默认可以传参数,默认的传参数就是默认的构造函数。重写构造函数的时候,必须调用默认的构造函数。 class类属性自带getter、setter方法 使用object时,不用new;使用class时要用new,并且new的时候,class中除了方法不执行,其他都只执行
4.判断if…else
val age =18
if (age < 18 ){
println("no allow")
}else if (18<=age&&age<=20){
println("允许与其他")
}else{
println("允许自我")
}
5.循环
for、while、do…while
1.to和until
/**
* 1 to 10 返回1到10的Range数组,包含10
* 1 until 10 返回1到10 Range数组 ,不包含10
*/
println(1 to 10 )//打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
res10: scala集合不可变范围包含= Range 1 to 10
res10: scala.collection.immutable.Range.Inclusive
println(1.to(10))//与上面等价,打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
println(1 to (10 ,2))//步长为2,从1开始打印 ,1,3,5,7,9
println(1.to(10, 2))
println(1 until 10 ) //不包含最后一个数,打印 1,2,3,4,5,6,7,8,9
println(1.until(10))//与上面等价
println(1 until (10 ,3 ))//步长为2,从1开始打印,打印1,4,7
for 循环
/**
* for 循环
* scala中 不能写count++ count-- 只能写count+
*/
for( i <- 1 to 10 ){
println(i)
}
/**
* 多层for循环
* 可以分号隔开,写入多个list赋值的变量,构成多层for循环
* /
//例子: 打印小九九
for(i <- 1 until 10 ;j <- 1 until 10){
if(i>=j){
print(i +" * " + j + " = "+ i*j+" ")
}
if(i==j ){
println()
}
}
/**
* 可以在for循环中加入条件判断
* /
for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
println(i)
}
/**
* 将for中的符合条件的元素通过yield关键字返回成一个集合
*/
val list = for(i <- 1 to 10 ; if(i > 5 )) yield i
3.while循环
/**
* while 循环
*/
var index = 0
while(index < 100 ){
println("第"+index+"次while 循环")
index += 1
}
index = 0
do{
index +=1
println("第"+index+"次do while 循环")
}while(index <100 )
Scala函数 1.定义 Scala函数根据有无参数划分为有参函数和无参函数
/**
* Scala函数的定义
*/
def fun (a: Int , b: Int ) : Unit = {
println(a+b)
}
fun(1,1)
def fun1 (a : Int , b : Int)= a+b
println(fun1(1,2))
注意: 1.函数的定义语法,用def来定义 2.可以定义传入的参数,要指定传入参数的类型 3.方法可以写返回值的类型也可以不写,函数会根据返回值自动判断,有时候不能省略,必须要写!!!例如:在递归函数中或者函数的返回值是函数类型 4.Scala中函数有返回值时,可以写return,也可以不写return。如果不写return,会将函数的最后一行当作结果返回。当写return时,必须要写函数的返回值 5.如果返回值可以一行搞定,可以将{}省略不写 6.传递给方法的参数可以在方法中使用,并且scala规定方法的传过来的参数为val的,不是var的 7.如果去掉方法体前面的等号,那么这个方法的返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit。假设,里面的逻辑最后返回了一个String,那么这个返回值会被转换位Unit,并且值会被丢弃
2.递归函数
/**
* 递归函数
* 5的阶乘
*/
def fun2(num :Int) :Int= {
if(num ==1)
num
else
num * fun2(num-1)
}
print(fun2(5))
3.包含参数默认值的函数
/**
* 包含默认参数值的函数
*/
def fun3(a :Int = 10,b:Int) = {
println(a+b)
}
fun3(b=2)
1.默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值 2.如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称
4.可变参数个数的函数 用逗号隔开
/**
* 包含默认参数值的函数
*/
def fun3(a :Int = 10,b:Int) = {
println(a+b)
}
fun3(b=2)
5.匿名函数 匿名函数不能显式声明函数的返回类型
/**
* 匿名函数
* 注意:
* 可以将匿名函数返回给定义的一个变量
*/
//有参数匿名函数
val value1 = (a : Int) => {
println(a)
}
value1(1)
//无参数匿名函数
val value2 = ()=>{
println("我爱Angelababy")
}
value2()
//有返回值的匿名函数
val value3 = (a:Int,b:Int) =>{
a+b
}
println(value3(4,4))
6.嵌套函数
/**
* 嵌套函数
* 例如:嵌套函数求5的阶乘
*/
def fun5(num:Int)={
def fun6(a:Int,b:Int):Int={
if(a == 1){
b
}else{
fun6(a-1,a*b)
}
}
fun6(num,1)
}
println(fun5(5))
7.偏应用函数 偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
/**
* 偏应用函数
*/
def log(date :Date, s :String)= {
println("date is "+ date +",log is "+ s)
}
val date = new Date()
log(date ,"log1")
log(date ,"log2")
log(date ,"log3")
//想要调用log,以上变化的是第二个参数,可以用偏应用函数处理
val logWithDate = log(date,_:String)
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")
8.高阶函数 函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型是函数的函数。
函数的参数是函数 函数的返回时函数 函数的参数和返回都是函数
/**
* 高阶函数
*/
//函数的参数是函数
def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
f(a,100)
}
def f(v1 :Int,v2: Int):Int = {
v1+v2
}
println(hightFun(f, 1))
//函数的返回是函数
//1,2,3,4相加
def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
def f2 (v1: Int,v2:Int) :Int = {
v1+v2+a+b
}
f2
}
println(hightFun2(1,2)(3,4))
//函数的参数是函数,函数的返回是函数
def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
f
}
println(hightFun3(f)(100,200))
println(hightFun3((a,b) =>{a+b})(200,200))
//以上这句话还可以写成这样
//如果函数的参数在方法体中只使用了一次 那么可以写成_表示
println(hightFun3(_+_)(200,200))
9.柯里化函数 可以理解为高阶函数的简化
/**
* 柯里化函数
*/
def fun7(a :Int,b:Int)(c:Int,d:Int) = {
a+b+c+d
}
println(fun7(1,2)(3,4))
字符串 1.String 2.StringBuilder 可变长度
/**
* String && StringBuilder
*/
val str = "abcd"
val str1 = "ABCD"
println(str.indexOf(97))
println(str.indexOf("b"))
println(str==str1)
/**
* compareToIgnoreCase
*
* 如果参数字符串等于此字符串,则返回值 0;
* 如果此字符串小于字符串参数,则返回一个小于 0 的值;
* 如果此字符串大于字符串参数,则返回一个大于 0 的值。
*
*/
println(str.compareToIgnoreCase(str1))
val strBuilder = new StringBuilder
strBuilder.append("abc")
// strBuilder.+('d')
strBuilder+ 'd'
// strBuilder.++=("efg")
strBuilder++= "efg"
// strBuilder.+=('h')
strBuilder+= 'h'
strBuilder.append(1.0)
strBuilder.append(18f)
println(strBuilder)
集合 1.数组 1.创建数组
/**
* 创建数组两种方式:
* 1.new Array[String](3)
* 2.直接Array
*/
//创建类型为Int 长度为3的数组
val arr1 = new Array[Int](3)
//创建String 类型的数组,直接赋值
val arr2 = Array[String]("s100","s200","s300")
//赋值
arr1(0) = 100
arr1(1) = 200
arr1(2) = 300
2.遍历数组
/**
* 遍历两种方式
*/
for(i <- arr1){
println(i)
}
arr1.foreach(i => {
println(i)
})
for(s <- arr2){
println(s)
}
arr2.foreach {
x => println(x)
}
3.二维数组
/**
* 创建二维数组和遍历
*/
val arr3 = new Array[Array[String]](3)
arr3(0)=Array("1","2","3")
arr3(1)=Array("4","5","6")
arr3(2)=Array("7","8","9")
for(i <- 0 until arr3.length){
for(j <- 0 until arr3(i).length){
print(arr3(i)(j)+" ")
}
println()
}
var count = 0
for(arr <- arr3 ;i <- arr){
if(count%3 == 0){
println()
}
print(i+" ")
count +=1
}
arr3.foreach { arr => {
arr.foreach { println }
}}
val arr4 = Array[Array[Int]](Array(1,2,3),Array(4,5,6))
arr4.foreach { arr => {
arr.foreach(i => {
println(i)
})
}}
println("-------")
for(arr <- arr4;i <- arr){
println(i)
} **2.List**
//创建
val list = List(1,2,3,4,5)
//遍历
list.foreach { x => println(x)}
// list.foreach { println}
/**
* list方法
*/
//filter
val list1 = list.filter { x => x>3 }
list1.foreach { println}
//count
val value = list1.count { x => x>3 }
println(value)
//map
val nameList = List(
"hello bjsxt",
"hello xasxt",
"hello shsxt"
)
val mapResult:List[Array[String]] = nameList.map{ x => x.split(" ") }
mapResult.foreach{println}
//flatmap
val flatMapResult : List[String] = nameList.flatMap{ x => x.split(" ") }
flatMapResult.foreach { println }
3.Set
//创建
val set1 = Set(1,2,3,4,4)
val set2 = Set(1,2,5)
//遍历
//注意:set会自动去重
set1.foreach { println}
for(s <- set1){
println(s)
}
println("*******")
/**
* Set方法举例
*/
//交集
val set3 = set1.intersect(set2)
set3.foreach{println}
val set4 = set1.&(set2)
set4.foreach{println}
println("*******")
//差集
set1.diff(set2).foreach { println }
set1.&~(set2).foreach { println }
//子集
set1.subsetOf(set2)
//最大值
println(set1.max)
//最小值
println(set1.min)
println("****")
//转成数组,list
set1.toArray.foreach{println}
println("****")
set1.toList.foreach{println}
//mkString
println(set1.mkString)
println(set1.mkString("\t"))
4.Map 1.Map创建
val map = Map(
"1" -> "bjsxt",
2 -> "shsxt",
(3,"xasxt")
)
注意 :创建map时,相同key被后面的相同的key顶替掉,只保留一个 2.获取值
println(map.get("1").get)
// getOrElse:如果map中没有对应项,赋值为getOrElse传的值
val result = map.get(8).getOrElse("no value")
println(result)
3.Map遍历
//遍历key
val keyIterable = map.keys
keyIterable.foreach { key => {
println("key:"+key+", value:"+map.get(key).get)
} }
println("---------")
4.key遍历
//遍历key
val keyIterable = map.keys
keyIterable.foreach { key => {
println("key:"+key+", value:"+map.get(key).get)
} }
println("---------")
5.value遍历
//遍历value
val valueIterable = map.values
valueIterable.foreach { value => {
println("value: "+ value)
} }
6.map合并
/**
* 合并map
* ++ 例:map1.++(map2) map1中加入map2
* ++: 例:map1.++:(map2) map2中加入map1
*/
val map1 = Map(
(1,"a"),
(2,"b"),
(3,"c")
)
val map2 = Map(
(1,"aa"),
(2,"bb"),
(2,90),
(4,22),
(4,"dd")
)
map1.++:(map2).foreach(println)
注意:合并map会将map中的相同key的value替换 7.map方法
//count
val countResult = map.count(p => {
p._2.equals("shsxt")
})
println(countResult)
//filter
map.filter(_._2.equals("shsxt")).foreach(println)
//contains:map中是否包含某个key
println(map.contains(2))
//exist:符合条件的记录存在不存在
println(map.exists(f =>{
f._2.equals("Angelababy")
}))
5.元组 1.定义 与列表一样,与列表不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的 2.元组创建与取值
/**
* 创建,最多支持22个
* 可以使用new,可以不适用new
*/
val tuple = new Tuple1(1)
val tuple2 = Tuple2("zhangsan",2)
val tuple3 = Tuple3(1,2,3)
val tuple4 = (1,2,3,4)
val tuple18 = Tuple18(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
val tuple22 = new Tuple22(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
//使用
//取值用"._XX"可以获取元组中的值
println(tuple2._1 + "\t"+tuple2._2)
val t = Tuple2((1,2),("zhangsan","lisi"))
println(t._1._2)
tuple最多支持22个参数
3.元组的遍历 先获取迭代器,然后再遍历
//遍历
val tupleIterator = tuple22.productIterator
while(tupleIterator.hasNext){
println(tupleIterator.next())
}
4.元组的常用方法
//翻转,只针对二元组
println(tuple2.swap)
//toString
println(tuple3.toString())
Trait 1.概念理解 Scala Trait(特征)相当于Java的接口,实际上它比接口功能强大。可以定义属性和方法的实现。 一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承 Trait(特征)定义的方式与类类似,使用关键字trait
2.例子:trait中带属性带方法实现
trait Read {
val readType = "Read"
val gender = "m"
def read(name:String){
println(name+" is reading")
}
}
trait Listen {
val listenType = "Listen"
val gender = "m"
def listen(name:String){
println(name + " is listenning")
}
}
class Person() extends Read with Listen{
override val gender = "f"
}
object test {
def main(args: Array[String]): Unit = {
val person = new Person()
person.read("zhangsan")
person.listen("lisi")
println(person.listenType)
println(person.readType)
println(person.gender)
}
}
注意: 继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义 trait不可以传参数
3.例子:trait中带方法不实现
object Lesson_Trait2 {
def main(args: Array[String]): Unit = {
val p1 = new Point(1,2)
val p2 = new Point(1,3)
println(p1.isEqule(p2))
println(p1.isNotEqule(p2))
}
}
trait Equle{
def isEqule(x:Any) :Boolean
def isNotEqule(x : Any) = {
!isEqule(x)
}
}
class Point(x:Int, y:Int) extends Equle {
val xx = x
val yy = y
def isEqule(p:Any) = {
p.isInstanceOf[Point] && p.asInstanceOf[Point].xx==xx
}
}
模式匹配 match 1.概念理解 模式匹配使用关键字match,一个模式匹配包含了一系列备选项。每个备选项都包含了一个模式及一到多个表达式。箭头符号=>隔开了模式和表达式 2.注意 模式匹配不仅可以匹配值还可以匹配类型 按照从上向下的顺序匹配,如果匹配到则不再往下匹配。如果都匹配不上,会匹配到case_,相当于default match的最外面的”{}”可以去掉看成一个语句
object Lesson_Match {
def main(args: Array[String]): Unit = {
val tuple = Tuple6(1,2,3f,4,"abc",55d)
val tupleIterator = tuple.productIterator
while(tupleIterator.hasNext){
matchTest(tupleIterator.next())
}
}
def matchTest(x:Any) ={
x match {
case x:Int=> println("type is Int")
case 1 => println("result is 1")
case 2 => println("result is 2")
case 3=> println("result is 3")
case 4 => println("result is 4")
case x:String => println("type is String")
// case x :Double => println("type is Double")
case _ => println("no match")
}
}
}
样例类(case class) 1.概念理解 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。 样例类默认帮你实现了toString,equals,copy和hashCode等方法。 样例类可以new, 也可以不用new;
case class Person1(name:String,age:Int)
object Lesson_CaseClass {
def main(args: Array[String]): Unit = {
val p1 = new Person1("zhangsan",10)
val p2 = Person1("lisi",20)
val p3 = Person1("wangwu",30)
val list = List(p1,p2,p3)
list.foreach { x => {
x match {
case Person1("zhangsan",10) => println("zhangsan")
case Person1("lisi",20) => println("lisi")
case _ => println("no match")
}
} }
}
}
Actor Model 1.概念理解 Actor Model是用来编写并行计算或分布式系统的高层次抽象(类似java中的Thread)让程序员不必为多线程模式下共享锁而烦恼,被用在Erlang 语言上, 高可用性99.9999999 % 一年只有31ms 宕机Actors将状态和行为封装在一个轻量的进程/线程中,但是不和其他Actors分享状态,每个Actors有自己的世界观,当需要和其他Actors交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外Actors回复,也不必暂停,每个Actors有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。 2.Actor特征 ActorModel是消息传递模型,基本特征就是消息传递 消息发送是异步的,非阻塞的 消息一旦发送成功,不能修改 Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的 3.什么是Akka Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和Scala 的 Actor 模型应用,底层实现就是Actor,Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。 spark1.6版本之前,spark分布式节点之间的消息传递使用的就是Akka,底层也就是actor实现的。1.6之后使用的netty传输。 4.代码示例
case class Message(actor:Actor,msg:Any)
class Actor1 extends Actor{
def act(){
while(true){
receive{
case msg :Message => {
println("i sava msg! = "+ msg.msg)
msg.actor!"i love you too !"
}
case msg :String => println(msg)
case _ => println("default msg!")
}
}
}
}
class Actor2(actor :Actor) extends Actor{
actor ! Message(this,"i love you !")
def act(){
while(true){
receive{
case msg :String => {
if(msg.equals("i love you too !")){
println(msg)
actor! "could we have a date !"
}
}
case _ => println("default msg!")
}
}
}
}
object Lesson_Actor2 {
def main(args: Array[String]): Unit = {
val actor1 = new Actor1()
actor1.start()
val actor2 = new Actor2(actor1)
actor2.start()
}
}
隐式转换系统 隐式转换,在编写程序的时候可以尽量少的去编写代码,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,提高代码质量
1.隐式值
//========================隐式值==============================
def sayName(implicit name:String) = {
println("say love to " + name)
}
implicit val name = "fanbingbing"
/**
* not enough arguments for method sayName: (implicit name: String)Unit. Unspecified value parameter name.
*/
/**
* ambiguous implicit values: both value a of type String and value name of type String match expected type String
* 隐式转换必须满足无歧义规则
* 在同一个作用域禁止声明两个类型一致的变量,防止在搜索的时候会犹豫不决
* 声明隐式参数的类型最好是自定义的数据类型,不要使用Int,String这些常用类型,防止碰巧冲突
*/
// implicit val a = "hhh"
sayName
/**
* 将name变量声明为implicit,编译器在执行sayName方法时发现缺少一个String类型的参数,此时会搜索作用域内类型为String的隐式值
并且将搜索到的隐式值作为sayName的参数值
*/
2.隐式视图 隐式转换为目标类型:把一种类型自动转换到另一种类型
//========================隐式视图 隐式转换为目标类型:把一种类型自动转换到另一种类型==============================
def addNum(num:Int) = {
num + 1000
}
implicit def stringToInt(num:String) = Integer.parseInt(num)
//type mismatch; found : String("1000") required: Int
println(addNum("1000"))
//========================隐式视图 通过隐式转换,能调用类中本不存在的方法==============================
implicit def fJJtoXTT(f:FJJ) = new XTT
//value jpContent is not a member of com.bjsxt.scala.FJJ
val fjj = new FJJ()
fjj.jpContent()
class FJJ{
}
class XTT{
def jpContent() = {
println("nengdaiwochifanjiuhaole")
}
}
3.隐式类 1.注意 (1)其所带的构造参数有且只能有一个 (2)隐式类必须被定义在类,伴生对象和包对象里 (3)隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾) (4)作用域内不能有与之相同名称的标示符
object Util{
implicit class StringLength(val s: String){
def getLength() = s.length
}
}
import com.hpe.scala.Util.StringLength
println("abc".getLength())
方法调用流程: 编译器在abc对象调用getLength时发现对象上并没有getLength方法,此时编译器就会在作用域范围内搜索隐式实体,发现有符合的隐式类可以用来转换成带有getLength方法的util类,最终调用getLength方法
参考文档
官网
http://www.scala-lang.org/download/
Scala学习笔记
https://www.jianshu.com/p/c16e0fae6ea2