Scala学习笔记
来源:互联网 发布:orcl 数据库未打开 编辑:程序博客网 时间:2024/05/22 08:29
基础
- 函数是一等公民
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
val squareVal = (a: Int) => a * a
def addOne(f: Int => Int, arg: Int) = f(arg) + 1
println("squareVal(2):" squareVal(2))
println("addOne(squareVal,2):" + addOne(squareVal, 2))
// squareVal(2):4
// addOne(squareVal,2):5
/******************************************************/
import scala.reflect.io.File
import java.util.Scanner
def withScanner(f: File, op: Scanner => Unit) = {
val scanner =new Scanner(f.bufferedReader)
try {
op(scanner)
} finally {
scanner.close()
}
}
withScanner(File("/proc/self/stat"),
scanner => println("pid is " + scanner.next()))
- 按名称传递参数
1
2
3
4
5
6
7
8
9
val logEnable =false
def log(msg:=> String) = // 多了"=>"符号,按值传递变为按名称传递
if (logEnable) println(msg)
val MSG ="programing is running"
log(MSG + 1 / 0) //没有除零的异常,参数到用的时候才计算,所以异常被跳过了
- 定义类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Persion(val firstName: String, val lastName: String) {
privatevar_age =0
def age =_age
def age_=(newAge: Int) =_age = newAge
def fullName() = firstName + " " + lastName
overridedef toString() = fullName()
}
val obama: Persion =new Persion("Barack", "Obama")
println("Persion: "+ obama)
println("firstName: " + obama.firstName)
println("lastName: " + obama.lastName)
obama.age_=(51)
println("age: " + obama.age)
- 鸭子类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def withClose(closeAble: { def close(): Unit },
op: { def close(): Unit } => Unit) { //使用{def close():Unit}作为参数,任何含有close()函数的类都可以作为参数
try {
op(closeAble) //第二个参数被调用,接着第一个参数被调用
} finally {
closeAble.close()
}
}
class Connection {
def close() = println("close Connection")
}
val conn: Connection =new Connection()
withClose(conn, conn =>
println("do something with Connection"))
- 柯里化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def withClose(closeAble: { def close(): Unit })
(op: { def close(): Unit } => Unit) {
try {
op(closeAble)
} finally {
closeAble.close()
}
}
class Connection {
def close() = println("close Connection")
}
val conn: Connection =new Connection()
withClose(conn)(conn =>
println("do something with Connection"))
/****************************************/
def add(x:Int, y:Int) = x + y //普通函数
def add(x:Int) = (y:Int) => x + y //柯里化的函数
def add(x:Int)(y:Int) = x + y //简化的写法
- 泛型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def withClose[A <: { def close(): Unit }, B](closeAble: A)
(f: A => B): B =
try {
f(closeAble)
} finally {
closeAble.close()
}
class Connection {
def close() = println("close Connection")
}
val conn: Connection =new Connection()
val msg = withClose(conn) { conn =>
{
println("do something with Connection")
"123456"
//123456
}
}
println(msg)
- Traits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
trait ForEachAble[A] {
def iterator: java.util.Iterator[A]
def foreach(f: A => Unit) = {
val iter = iterator
while (iter.hasNext)
f(iter.next)
}
}
trait JsonAble {
def toJson() =
scala.util.parsing.json.JSONFormat.defaultFormatter(this)
}
// 使用with关键字混入foreach和toJson的功能
val list =new java.util.ArrayList[Int]() with ForEachAble[Int] with JsonAble
list.add(1); list.add(2)
println("For each: "); list.foreach(x => println(x))
println("Json: " + list.toJson())
函数式
- 模式匹配
1
2
3
4
5
6
7
8
9
10
def fibonacci(in: Any): Int = in match {
case0=> 0
case1=> 1
case n: Int if(n>1) => fibonacci(n - 1) + fibonacci(n - 2) // if语句排除负数
case n: String => fibonacci(n.toInt) //匹配String类型
case_=> 0 //匹配所有情况
}
println(fibonacci(3))
println(fibonacci(-3))
println(fibonacci("3"))
- Case Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstractclass Expr
caseclass FibonacciExpr(n: Int) extends Expr {
require(n >=0)
}
caseclass SumExpr(a: Expr, b: Expr) extends Expr
def value(in: Expr): Int = in match {
case FibonacciExpr(0) => 0
case FibonacciExpr(1) => 1
case FibonacciExpr(n) =>
value(SumExpr(FibonacciExpr(n - 1), FibonacciExpr(n - 2)))
case SumExpr(a, b) => value(a) + value(b)
case_=> 0
}
println(value(FibonacciExpr(3)))
- 函数式例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
val list = List(1, 2, 3, 4)
def containsOdd(list: List[Int]): Boolean = {
for (i <- list) {
if (i %2==1)
returntrue;
}
returnfalse;
}
println("list contains Odd ? " + containsOdd(list))
println("list contains Odd ? " + list.exists((x:Int) => x%2==1))
println("list contains Odd ? " + list.exists(_%2 ==1))
/*********************************************************/
val file = List("warn 2013 msg", "warn 2012 msg",
"error 2013 msg", "warn 2013 msg")
println("cat file | grep 'warn' | grep '2013' | wc : "
+ file.filter(_.contains("warn")).filter(_.contains("2013")).size)
/******************map and reduce******************************/
val file = List("warn 2013 msg", "warn 2012 msg",
"error 2013 msg", "warn 2013 msg")
def wordcount(str: String): Int = str.split(" ").count("msg" ==_)
val num = file.map(wordcount).reduceLeft(_ + _)
println("wordcount:" + num)
- 尾递归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
val file = List("warn 2013 msg", "warn 2012 msg",
"error 2013 msg", "warn 2013 msg")
def wordcount(str: String): Int = str.split(" ").count("msg" ==_)
def foldLeft(list: List[Int])(init: Int)(f: (Int, Int) => Int): Int = {
list match {
case List() => init
case head :: tail => foldLeft(tail)(f(init, head))(f)
}
}
val num = foldLeft(file.map(wordcount))(0)(_ + _)
println("wordcount:" + num)
//wordcount:4
- 更强大的for循环
1
2
3
4
5
6
7
8
9
10
11
12
13
val file = List("warn 2013 msg", "warn 2012 msg",
"error 2013 msg", "warn 2013 msg")
def wordcount(str: String): Int = str.split(" ").count("msg" ==_)
val counts =
for (line <- file)
yield wordcount(line)
val num = counts.reduceLeft(_ + _)
println("wordcount:" + num)
//wordcount:4
- Option
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def getProperty(name: String): Option[String] = {
val value = System.getProperty(name)
if (value !=null) Some(value) else None
}
val osName = getProperty("os.name")
osName match {
case Some(value) => println(value)
case_=> println("none")
}
//Linux
println(osName.getOrElse("none"))
//Linux
osName.foreach(print _)
//Linux
- Lazy初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ScalaCurrentVersion(val url: String) {
lazyval source= {
println("fetching from url...")
scala.io.Source.fromURL(url).getLines().toList
}
lazyval majorVersion = source.find(_.contains("version.major"))
lazyval minorVersion = source.find(_.contains("version.minor"))
}
val version =new ScalaCurrentVersion(
"https://raw.github.com/scala/scala/master/build.number")
println("get scala version from " + version.url)
version.majorVersion.foreach(println _)
version.minorVersion.foreach(println _)
并发
- 使用Actor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import akka.actor.{ Actor, ActorSystem, Props }
val system = ActorSystem() //开始
class EchoServer extends Actor { //继承
def receive = { //接受消息
case msg: String => println("echo " + msg)
}
}
val echoServer = system.actorOf(Props[EchoServer]) //创建
echoServer ! "hi" //发送
system.shutdown //结束
/************************Actor更简化的用法********************************/
import akka.actor.ActorDSL._
import akka.actor.ActorSystem
implicitval system = ActorSystem()
val echoServer = actor(new Act {
become {
case msg => println("echo " + msg)
}
})
echoServer ! "hi"
system.shutdown
- Actor原理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import akka.actor.{ Actor, Props, ActorSystem }
import akka.testkit.CallingThreadDispatcher
implicitval system = ActorSystem()
class EchoServer(name: String) extends Actor {
def receive = {
case msg => println("server" + name + " echo " + msg +
" by " + Thread.currentThread().getName())
}
}
val echoServers = (1 to 10).map(x =>
system.actorOf(Props(new EchoServer(x.toString))
.withDispatcher(CallingThreadDispatcher.Id)))
(1 to 10).foreach(msg =>
echoServers(scala.util.Random.nextInt(10)) ! msg.toString)
system.shutdown
Actor比线程轻量。在Scala中可以创建数以百万级的Actor。奥秘在于Actor直接可以复用线程。
Actor和线程是不同的抽象,他们的对应关系是由Dispatcher决定的。
这个例子创建4个Actor,每次调用的时候打印自身线程名称。
可以发现Actor和线程之间没有一对一的对应关系。一个Actor可以使用多个线程,一个线程也会被多个Actor复用。
- 同步返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import akka.actor.ActorDSL._
import akka.pattern.ask
implicitval ec = scala.concurrent.ExecutionContext.Implicits.global
implicitval system = akka.actor.ActorSystem()
val versionUrl ="https://raw.github.com/scala/scala/master/starr.number"
val fromURL = actor(new Act {
become {
case url: String => sender ! scala.io.Source.fromURL(url)
.getLines().mkString("\n")
}
})
val version = fromURL.ask(versionUrl)(akka.util.Timeout(5 * 1000))
version.foreach(println _)
system.shutdown
Actor非常适合于较耗时的操作。比如获取网络资源。
这个例子通过调用ask函数来获取一个Future。
在Actor内部通过 sender ! 传递结果。
Future像Option一样有很多高阶方法,可以使用foreach查看结果。
- 异步返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import akka.actor.ActorDSL._
import akka.pattern.ask
implicitval ec = scala.concurrent.ExecutionContext.Implicits.global
implicitval system = akka.actor.ActorSystem()
val versionUrl ="https://raw.github.com/scala/scala/master/starr.number"
val fromURL = actor(new Act {
become {
case url: String => sender ! scala.io.Source.fromURL(url)
.getLines().mkString("\n")
}
})
val version = fromURL.ask(versionUrl)(akka.util.Timeout(5 * 1000))
version onComplete {
case msg => println(msg); system.shutdown
}
异步操作可以最大发挥效能。Scala的Futrue很强大,可以异步返回。
可以实现Futrue的onComplete方法。当Futrue结束的时候就会回调。
在调用ask的时候,可以设定超时。
- 并行集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
val urls = List("http://scala-lang.org",
"https://github.com/yankay/scala-tour")
def fromURL(url: String) = scala.io.Source.fromURL(url)
.getLines().mkString("\n")
val t = System.currentTimeMillis()
//urls.map(fromURL(_))
urls.par.map(fromURL(_)) //并发执行
println("time: "+ (System.currentTimeMillis - t) + "ms")
/********************************************************/
val file = List("warn 2013 msg", "warn 2012 msg",
"error 2013 msg", "warn 2013 msg")
def wordcount(str: String): Int = str.split(" ").count("msg" ==_)
val num = file.par.map(wordcount).par.reduceLeft(_ + _) // 并发执行
println("wordcount:" + num)
- 远程Actor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import akka.actor.{ Actor, ActorSystem, Props }
import com.typesafe.config.ConfigFactory
implicitval system = akka.actor.ActorSystem("RemoteSystem",
ConfigFactory.load.getConfig("remote"))
class EchoServer extends Actor {
def receive = {
case msg: String => println("echo " + msg)
}
}
val server = system.actorOf(Props[EchoServer], name ="echoServer")
val echoClient = system
.actorFor("akka://RemoteSystem@127.0.0.1:2552/user/echoServer")
echoClient ! "Hi Remote"
system.shutdown
Actor是并发模型,也使用于分布式。
这个例子创建一个Echo服务器,通过actorOf来注册自己。
然后再创建一个client,通过akka url来寻址。
除了是通过url创建的,其他使用的方法和普通Actor一样。
实践
- 使用Java
1
2
3
4
5
6
7
8
import org.apache.commons.beanutils.BeanUtils
import scala.beans.BeanProperty
//用@BeanProperty注解来生成Java Style的Bean
class SimpleBean(@BeanProperty var name: String) {
}
val bean =new SimpleBean("foo")
println(BeanUtils.describe(bean))
- 相等性
1
2
3
4
5
6
7
8
9
10
11
12
class Person(val name: String) {
overridedef equals(other: Any) = other match {
case that: Person => name.equals(that.name)
case_=> false
}
}
caseclass Test(val name:String, val age:Int){ // case类自动生成正确的equals方法
}
println(new Person("Black") ==new Person("Black"))
println(new Test("Black",12) ==new Test("Black",12))
- 抽取器
1
2
3
4
5
6
7
8
9
10
11
12
13
import scala.util.matching.Regex
object Email {
def unapply(str: String) =new Regex("""(.*)@(.*)""")
.unapplySeq(str).get match {
case user :: domain :: Nil => Some(user, domain)
case_=> None
}
}
"user@domain.com"match {
case Email(user, domain) => println(user + "@" + domain)
}
抽取器可以帮助模式匹配进行解构。
Scala的正则表达式会自带抽取器,可以抽取出一个List。List里的元素是匹配()里的表达式。
- Scala学习笔记1
- Scala学习笔记2
- scala语言学习笔记
- Scala学习笔记
- scala学习笔记01
- Scala学习笔记02
- Scala学习笔记03
- Scala学习笔记04
- scala学习笔记:集合
- scala学习笔记01
- Scala学习笔记02
- Scala学习笔记03
- Scala学习笔记04
- Scala学习笔记
- Scala开发学习笔记
- Scala学习笔记一
- Scala学习笔记二
- Scala学习笔记三
- 一、C++ 函数指针
- Java中初始化顺序
- linux 下的软链和硬链
- Genymotion加速下载虚拟镜像速度慢失败Connection timeout
- 深入学习java并发编程:CopyOnWriteArrayList<E>实现
- Scala学习笔记
- STM32F0xx_DMA收发USART数据配置详细过程
- 6、单例模式
- Merge k Sorted Arrays
- application共享变量
- 键盘回车事件导致页面刷新
- xml解析之使用dom4j的api对xml文件进行CRUD(二)
- Java 正则表达式
- ldpack工作日记-2016/5/30