scala常见的操作
1. scala是什么
Scala是一门主要以Java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程语言的最佳特性综合在一起的编程语言。
RERL: “读取-求值-打印”。解释器读取到一个表达式,对它求值,将它打印出来 ,然后再接着继续读取下一个表达式。
2. 语法糖
2.1 基础语法
-
scala有两种变量, val(推荐)和var。 val 是常量,后继不可更新。 var是变量。
如果不明确指明声明数据类型,则Scala会自动进行类型推断
scala为什么推荐使用常量?
对是常量来说,避免多线程并发
-
基础类型:Double , Float, Long, Int, Short, Byte, Unit(空), Boolean , char。
scala基础类型中没有String, Scala调用的是java.lang包下的String
-
操作符和方法
-
1 + 2 是 1.+(2)的简写
-
21.5 min 12.5
Scala里的操作符不是特殊的语法,任何方法都可以是操作符。到底是方法还是操作符取决于你如何使用。
-
-
操作符分类
-
前缀操作符(操作数在操作符右侧)
-
中缀操作符(两个操作数,分别在操作符左右两侧
-
后缀操作符(操作数在操作符左侧)
-
-
操作符相等性
- java中
equals
判断两个值 是否相等==
判断地址,是否相同
- Scala中,只有
==
该操作对所有对象都起作用,而不仅仅是基本类型
- java中
-
富包装(每一个类型都包含一个富类型)
-
条件控制
// 单条控制语句 val fileName = "flume-ng.conf" val confFile = if (fileName.isEmpty) "default.conf" else fileName println(confFile) //if 语句(函数式风格) println(if (!fileName.isEmpty) fileName else "default.conf")
-
循环
// while 多用业务逻辑中,需要重复执行的代码块 var falg = true var counter = 0 while(falg) { if(count > 10) falg = false counter += 1 } println(counter) // for循环 // 单行 var arr = Array(1, 2, 3, 4, 5, 6) for (ele <- arr) println("element: " + ele) for (i <- 0 until arr.length) println("element: " + arr(i)) for (i <- 0 to arr.length -1 ) println("element: " + arr(i)) // 自带守卫, 注意在if之前 没有分号 for (ele <- arr if ele > 4) println("element: " + ele) // 变量<-表达式的形式提供多个生成器 for( i<-1 to 3; j<-1 to 3) print((10 * i + j) + " ") // 多行 val arr = Array(1, 2, 3, 4, 5, 6) for (ele <- arr) { println("element: " + ele) } // 函数式 val arr = Array(1, 2, 3, 4, 5, 7) arr.foreach(ele => println("element: " + ele)) arr.foreach(ele => println("element: " + _)) // yield 将集合攒着 然后返回一个生成器给result val result = for( x <- 1 to 10) yield x * 2 result.foreach(println)
-
scala中没有break continue
-
匹配表达式
val sex = "men" sex match { case "men" => println("I'm man") case "woman" => println("I'm woman") case _ => println("what Fuck!") //_的第一个用法 }
2.2 函数
-
Unit 函数(返回值为空的函数)
def processLine(fileName: String, width: Int, line: String): Unit = { if(line.length > width) { println("fileName: " + fileName) } }
-
单行函数
def max_value (x: Int, y: Int) : Int = if ( x>y ) x else y println(max_value(10, 20))
-
头等函数(匿名函数)
val inc_num = (x:Int) => x + 1 print(inc_num(10))
-
多语句头等函数
val print_arr = (x: Int, y: Int) => { println("x: " + x) println("y: " + y) x + y } print_arr(10, 20)
-
占位符语法
只要每个参数在头等函数内只出现一次, 就可以将下划线用做占位符使用
var list = List(1, 2, 3, 4, 5, 6) list = list.filter(_ > 3) list.foreach(println _ )
-
变长参数
def main(args: Array[String]): Unit = { getUserInfo(1001, "Mike", "men", "higer", "handSome") } def getUserInfo(id: Int, userName: String, args: String*): Unit = { println("id: " + id) println("userName: " + userName) args.foreach(println) }
2.3 类和对象
类是对象的蓝图。定义了类,就可以通过new关键字进行对象的实例化操作。
面向对象的最主要的特征:责任分工
- 任何一个业务系统,都是由多个对象交互而成
- 任何一个对象不孤立存在,对象与对象之间一定存在交互
好处: 责任分工
- 当我们业务系统某个功能出现问题时, 不会导致整个系统 无法工作, 我们只需要定位到某个出问题的对象进行解决即可。
- 在这个过程中,其他对象不会受到影响
什么是类?
什么是对象?
类与对象的区别?
单独拿出来说,不好说不清楚的。
- 任何一个业务系统都是由多个对象交互而成。
- 为了能使多个对象交互来完成整个业务系统, 所以我们需要使用类来定义不同对象的属性和行为。
- 类是定义对象的模版,对象是实际完成业务系统功能的最小单元组成单元。
2.3.1 封装
- 封装的好处
- 保证每个对象的完整性
- 保证对象与对象之间的隔离性
class User {
private var id = 1001
private var name = "bob"
private var age = 18
} // 通过 getter setter访问
class User {
private var userId: Int = _
private var userName: String = _
private var userAge: Int = _
def getUserId: Int = this.userId
def setUserId(newValue: Int): Unit = {
this.userId = userId
}
}
-
主构造器
class User (id: Int, name: String, age: Int) { private var userId = id private var userName = name private var userAge = age def show(): Unit = { println("UserId: " + this.userId + " userName: " + this. userName " userAge: " + this.userAge) } }
-
方法重写
override def toString: String = { "userId: " + this.userId + ", userName: " + this.userName + ", userAge:" + this.userAge }
-
先决条件
class User(id: Int, name: String, age: Int) { require (age > 18) require (!name.isEmpty) private var userId = id private var userName = name private var userAge = age }
-
主构造器与辅助构造器
class User (id: Int, name: String,) { private var userId = id private var userName = name private var userAge = age def this(id: Int, name:String, age: Int) { this(id, name, age) this.userId = id this.userName = name } def show(): Unit = { println("UserId: " + this.userId + " userName: " + this. userName " userAge: " + this.userAge) } }
2.3.2 继承
- public 共有
- private 私有
- protected 同一个包下,以及其继承的子类
- friendly(default) 同一个包下
abstarct class Father {
def say(): Unit = {
println(" I'm your daddy")
}
def eat(): Unit
}
class Son extends Father {
override def say(): Unit = {
println("hello baba")
}
override def eat(): Unit = {
println("what fuck???")
}
}
继承,它的缺点?
- 只支持单继承
只能单继承,但可以多实现
2.3.3 多态
-
特质 Trait
// 特质的定义除了使用trait关键字之外,与类无异 trait Employee { def work(thing: String): Unit } abstract class Human { def eat(food: String): Unit } class Person extends Human with Employee { override def eat(food: String) : Unit = { println("I'm eatting " + food) } override def work(thing: String) : Unit = { println("I'm working " + thing) } }
2.4 object对象
-
单例对象。 Scala中没有静态方法或静态字段, 可以通过object达到同样的目的。object对象定义了某个类的的单个实例,包含了你想要的特性。
class Server(val ipAddr: String, val host: String, val net: String) { private var ipAddress = ipAddr private var hostName = host private var netMask = net override def toString = s"Server($ipAddress, $hostName, $netMask)" } object Server { private var uniqueNumber: Int = 0 def getUniqueNumber(): Int = { uniqueNumber += 1 uniqueNumber } }
-
伴生对象
-
某种场合下,需要用有静态方法又要有实例方法的类。
-
在Scala中,通过伴生对象来达到同样的目的。类和它的伴生对象可以相互访问私有特性,但必须保存在同一个源文件中。
class Account { val accountNumber = Account.newUniqueNumber private var balace = 0.0 def showMoney(): Unit = { println("balance: " + balace) } } object Account{ private var lastNumber = 0 private def newUniqueNumber( ): Int ={ lastNumber += 1 lastNumber } def showMoney(account: Account): Unit = { println("balance: " + account.balace) } }
-
-
应用程序对象
object hello extends App { println("Hello Scala") }
-
枚举。与Java和C++不同,Scala并没有枚举类型。不过提供了一个
Enumeration
助手类,可以用于产生枚举// 应用场景:协同开发,需要进行变量名、内容统一时 object EnumColor extends Enumeration { val Red, Yellow, Blue = Value }
2.5 包的可见性
-
可以当前属性在哪些包下可见
package com.max.entity class User { private[entity] val userId = 1001 private[entity] val userName = "Bob" private[entity] val age = 18 private[this] val realName = "John" }
2.6 集合类型
-
定长集合
val names = new Array[String](10) val arr = new Array("MAX", "Mike") arr(0) = "bob" println(arr.mkString(","))
scala中的Array是以Java数组方式实现的,例如java.lang.String[]
-
不定长集合
import scala.collection.mutable.ArrayBuffer val buffer = new ArrayBuffer[Int]() buffer += 1 buffer += (2, 3, 4, 5) println(buffer.mkString(","))
2.7 映射
-
构建映射
// 不可变Map val immuScores = Map("Bob"-> 18, "azheng" -> 16, "aqiang" -> 18) // 可变Map val mmuScores = scala.collection.mutable.Map("Bob"-> 18, "azheng" -> 16, "aqiang" -> 18) immuScores("azheng") = 20 mmuScores2("azheng") = 20 // 获取元素, 如果元素不存在则会 抛异常 val bob = immuScores("Bob") // 元素不存在则返回None val aZhen = immuScores.get("Bob") println(immu_scores) println(immu_scores2) // 迭代映射 for(k <- mmuScores.keys) println(k) for(v <- mmuScores.values) println(v) for((k,v) <- mmuScores) print((k, v))
2.8 元组
-
是不同类型的值聚集
// 声明元组只有一种类型 val t1 = Tuple1(10) val t2 = ("men", 10) val t3 = ("mike", "men", 20) println(t1._1) println(t2._1, t2._2) println(t3._1, t3._2,t3._3)
2.9 样例类
-
是一种特殊类,常用模式匹配与actor中
case class Person(name: String, age: Int) val person = Person("John", 18) println("name: " + person.name + "age: " + person.age)
3 泛型
如果不用泛型会怎么样?
- 无法预估以及约束人为操作
- JVM在每次加载这些没有指定泛型的集合时,会执行类型检查 , 又会产生性能开销。
使用泛型的好处
- 解决人为误操作问题
- 在编译阶段就能对集合元素进行检查 ,减少开销
-
泛型类
class Pair[K, V] (val keys: K, val values: V) { var key = keys var value = values }
-
泛型函数
def getMiddle[T](arr: Array[T]): Int = { arr.length / 2 }
4. 隐式转换
当前程序在程序的过程中,如果出现需要类型转换的操作。
优先会在当前程序的作用域中寻找可用的implicit关键字的标准隐式转换函数
implicit def strToInt(s: String) : Int = s.toInt
implicit def add(s: Int, y: Int) : Int = x + y
def main(args: Array[String]): Unit = {
val s: String = "100"
val i: Int = 100
println(add(s,i))
}
5. Actor并发编程
-
进程
进程是操作系统中的最小的资源分配单元
一个进程包含多个线程 进程也是操作系统中可执行单元
-
线程
线程是操作系统中最小的执行单元
-
模拟聊天式
// User1Actor 相当于 用户1 package com.message.domain import scala.actors._ import com.message.domain.CaseCasses._ class User1Actor extends Actor{ override def act(): Unit = { while (true) { receive { case MyMessage(content, sender) => { println("小林接收到消息:" + content) val message = readLine("小林:") sender ! MyMessage(message, this) } case Login(userName:String, passWord:String) => { println("UserName: " + userName) println("PassWord:" + passWord) println("登陆成功") } case Register(userName:String, passWord: String, age: Int) => { println("UserName: " + userName) println("PassWord:" + passWord) println("Age:" + age) println("注册成功") } case _ => println("啦啦啦啦啦") } } } } //User2Actor 用户2 package com.message.domain import com.message.domain.CaseCasses._ import scala.actors._ class User2Actor(server: User1Actor) extends Actor{ override def act(): Unit = { var msg = readLine("小明:") server ! MyMessage(msg, this) while (true) { receive { case MyMessage(content, sender) => { println("小明接收到消息:" + content) val message = readLine("小明:") sender ! MyMessage(message, this) } } } } } // CaseCasees样例类 package com.message.domain object CaseCasses { import scala.actors._ case class MyMessage(content: String, sender: Actor) case class Login(userName: String, passWord: String) case class Register(userName: String, passWord: String, age:Int) }