文章目录
Scala介绍
首先Scala是一门基于JVM的编程语言,具有很好的兼容性和并发性。
Scala六大特征
- Java和Scala可以无缝混编
- 类型推测(自动推测类型)
- 并发和分布式
- 特质trait,特征(类似于java中interface和abstract结合,可以实现多继承)
- 模式匹配(类似于java switch)
- 高阶函数(包含两种:①函数的参数是函数②函数的返回是函数)
Scala的安装与配置
1,下载安装包
官网下载scala2.10:https://www.scala-lang.org/download/2.10.4.html
2,配置环境变量(和配置jdk相似)
//首先配置SCALA_HOME
SCALA_HOME=“scala的解压路径”
//然后配置path
;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin
3,编译器配置
3.1,eclipse配置Scala插件
下载插件(一定要对应eclipse版本下载)
http://scala-ide.org/download/prev-stable.html
解压后把features和plugins两个文件夹拷贝到eclipse安装目录中的” dropins/scala”目录下。
3.2,或者使用scala ide
下载网址:http://scala-ide.org/download/sdk.html
3.3,idea中配置scala插件
①打开idea,close项目后,点击Configure->Plugins
②搜索scala,点击安装
③设置jdk,打开Project Structure,点击new 选择安装好的jdk路径
④创建scala项目,配置scala sdk(Software Development Kit)
Scala基础
1,数据类型
2,变量与常量的声明
变量:用var定义,可修改
常量:用val定义,不可修改
例子:
var name="zhangsan"
val gender="man"
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)
}
}
注意apply方法的使用:apply方法是在类加载的时候启动放入,所以可以初始化一些信息,例如:我们在apply方法中new 对象,那么在我们main方法中实例化对象中省去new。
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)
}
}
注意事项:
- 建议类名首字母大写 ,方法首字母小写,类和方法命名建议符合驼峰命名法。
- scala 中的object是单例对象,相当于java中的工具类,可以看成是定义静态的方法的类。object不可以传参数。另:Trait不可以传参数
- scala中的class类默认可以传参数,默认的传参数就是默认的构造函数。
重写构造函数的时候,必须要调用默认的构造函数。 - class 类属性自带getter ,setter方法。
- 使用object时,不用new,使用class时要new ,并且new的时候,class中除了方法不执行,其他都执行。
- 如果在同一个文件中,object对象和class类的名称相同,则这个对象就是这个类的伴生对象,这个类就是这个对象的伴生类。可以互相访问私有变量。
4,if else的使用
/**
* if else
*/
val age =18
if (age < 18 ){
println("no allow")
}else if (18<=age&&age<=20){
println("allow with other")
}else{
println("allow self")
}
5,for ,while,do…while的使用
/**
* 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
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
6,创建for循环
for( i <- 1 to 10 ){
println(i)
}
7,创建多层for循环
var count = 0;
for(i <- 1 to 10; j <- 1 until 10){
println("i="+ i +", j="+j)
count += 1
}
println(count);
//例子: 打印小九九
for(i <- 1 until 10 ;j <- 1 until 10){
if(i>=j){
print(i +" * " + j + " = "+ i*j+" ")
}
if(i==j ){
println()
}
}
8,带判断条件的for循环
for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
println(i)
}
9. scala中不能使用count++,count—只能使用count = count+1 ,count += 1
10. for循环用yield 关键字返回一个集合
11. while循环,while(){},do {}while()
Scala函数
- 函数定义语法 用def来定义
- 可以定义传入的参数,要指定传入参数的类型
- 方法可以写返回值的类型也可以不写,会自动推断,有时候不能省略,必须写,比如在递归函数中或者函数的返回值是函数类型的时候。
- scala中函数有返回值时,可以写return,也可以不写return,会把函数中最后一行当做结果返回。当写return时,必须要写函数的返回值。
- 如果返回值可以一行搞定,可以将{}省略不写
- 传递给方法的参数可以在方法中使用,并且scala规定方法的传过来的参数为val的,不是var的。
- 如果去掉方法体前面的等号,那么这个方法返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit.假设,里面的逻辑最后返回了一个string,那么这个返回值会被转换成Unit,并且值会被丢弃。
scala几大函数
- 普通函数
- 带默认值的函数
- 递归函数
- 可变参数个数的函数
- 匿名函数
- 嵌套函数
- 偏应用函数
- 高阶函数
- 柯里化函数
1,普通函数
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))
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)
4,可变参数个数的函数
def fun4(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun4(1,2,3,4))
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,嵌套函数
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))
Scala字符串
-
String定长字符串
-
StringBuilder可变长度字符串
-
常用操作方法
比较:equals
忽略大小写比较:equalsIgnoreCase
查找:indexOf,返回游标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)
Scala集合
数组
1,创建数组
new Array[Int](10)
赋值:arr(0) = xxx
Array[String](“s1”,”s2”,”s3”)
2,数组遍历
for
foreach
3,创建一维数组和二维数组
4,数组中方法举例
Array.concate:合并数组
Array.fill(5)(“bjsxt”):创建初始值的定长数组
list集合
1.创建list
val list = List(1,2,3,4)
Nil长度为0的list
2.list遍历
foreach ,for
3.list方法举例
filter:过滤元素
count:计算符合条件的元素个数
map:对元素操作
flatmap :压扁扁平,先map再flat
//创建
val list = List(1,2,3,4,5)
//遍历
list.foreach { x => println(x)}
// list.foreach { println}
//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 }
set集合
- 创建set
注意:set集合会自动去重 - set遍历
foreach,for - set方法举例
交集:intersect ,&
差集: diff ,&~
子集:subsetOf
最大:max
最小:min
转成数组,toList
转成字符串:mkString(“~”)
Map KV键值对集合
- map创建
Map(1 –>”bjsxt’)
Map((1,”bjsxt”))
val map = Map(
"1" -> "bjsxt",
2 -> "shsxt",
(3,"xasxt")
)
- 获取map的值
map.get(“1”).get
map.get(100).getOrElse(“no value”):如果map中没有对应项,赋值为getOrElse传的值。
//获取值
println(map.get("1").get)
val result = map.get(8).getOrElse("no value")
println(result)
- 遍历map
//map遍历 for,foreach
for(x <- map){
println("====key:"+x._1+",value:"+x._2)
}
map.foreach(f => {
println("key:"+ f._1+" ,value:"+f._2)
})
- 遍历key
//遍历key map.keys
val keyIterable = map.keys
keyIterable.foreach { key => {
println("key:"+key+", value:"+map.get(key).get)
} }
println("---------")
- 遍历value
//遍历value map.values
val valueIterable = map.values
valueIterable.foreach { value => {
println("value: "+ value)
} }
- 合并map
++ 例:map1.++(map2) --map1中加入map2
++: 例:map1.++:(map2) –map2中加入map1
注意:合并map会将map中的相同key的value替换
//合并map
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中的方法举例
- filter:过滤,留下符合条件的记录
- count:统计符合条件的记录数
- contains:map中是否包含某个key
- exist:符合条件的记录存在不存在
/**
* map方法
*/
//count
val countResult = map.count(p => {
p._2.equals("shsxt")
})
println(countResult)
//filter
map.filter(_._2.equals("shsxt")).foreach(println)
//contains
println(map.contains(2))
//exist
println(map.exists(f =>{
f._2.equals("Angelababy")
}))
元组
1. 元组定义
与列表一样,与列表不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的。
2. 创建元组与取值
- val tuple = new Tuple(1) 可以使用new
- val tuple2 = Tuple(1,2) 可以不使用new,也可以直接写成val tuple3 =(1,2,3)
- 取值用”._XX” 可以获取元组中的值
注意:tuple最多支持22个参数
//创建,最多支持22个
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)
//使用
println(tuple2._1 + "\t"+tuple2._2)
val t = Tuple2((1,2),("zhangsan","lisi"))
println(t._1._2)
3. 元组的遍历
//遍历
val tupleIterator = tuple22.productIterator
while(tupleIterator.hasNext){
println(tupleIterator.next())
}
4. swap,toString方法
//翻转,只针对二元组
println(tuple2.swap)
//toString
println(tuple3.toString())
trait 特性
1. 概念理解
Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。
与接口不同的是,它还可以定义属性和方法的实现。
一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。
2. 举例:trait中带属性带方法实现
注意:
- 继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。
- 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)
}
}
模式匹配match
1. 概念理解:
Scala 提供了强大的模式匹配机制,应用也非常广泛。
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。
每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
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())
}
}
/**
* 注意点:
* 1.模式匹配不仅可以匹配值,还可以匹配类型
* 2.模式匹配中,如果匹配到对应的类型或值,就不再继续往下匹配
* 3.模式匹配中,都匹配不上时,会匹配到 case _ ,相当于default
*/
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 classes)
1. 概念理解
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类。实现了类构造参数的getter方法(构造参数默认被声明为val),当构造参数是声明为var类型的,它将帮你实现setter和getter方法。
- 样例类默认帮你实现了toString,equals,copy和hashCode等方法。
- 样例类可以new, 也可以不用new
2. 例子:结合模式匹配的代码
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有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。
Actor的特征:
- ActorModel是消息传递模型,基本特征就是消息传递
- 消息发送是异步的,非阻塞的
- 消息一旦发送成功,不能修改
- Actor之间传递时,自己决定决定去检查消息,而不是一直等待,是异步非阻塞的
什么是Akka
Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和Scala 的 Actor 模型应用,底层实现就是Actor,Akka是一个开发库和运行环境,可以用于构建高并发、分布式、可容错、事件驱动的基于JVM的应用。使构建高并发的分布式应用更加容易。
spark1.6版本之前,spark分布式节点之间的消息传递使用的就是Akka,底层也就是actor实现的。1.6之后使用的netty传输。
2. 例:Actor简单例子发送接收消息
import scala.actors.Actor
class myActor extends Actor{
def act(){
while(true){
receive {
case x:String => println("save String ="+ x)
case x:Int => println("save Int")
case _ => println("save default")
}
}
}
}
object Lesson_Actor {
def main(args: Array[String]): Unit = {
//创建actor的消息接收和传递
val actor =new myActor()
//启动
actor.start()
//发送消息写法
actor ! "i love you !"
}
}
3. 例:Actor与Actor之间通信
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()
}
}