Scala 入门笔记
Scala
函数式编程:感觉spark一般用scala写,甚至spark源码就是用scala实现的,所以就学习一下scala
基础
/**
* 基础语法
*/
object base {
def hello1(name:String):String = {
s"my name is ${name}"
}
def hello2(name:String) = s"my name is ${name}"
def study_for() = {
val li = List(1,2,3,4,5)
for(
s <- li
)println("first_for : "+s)
for(
s <- li
if s > 2
)println("second_for : "+s)
println(
for(
s <- li
if s < 3
)yield (s)
)
}
def study_try() = {
try {
Integer.parseInt("dog")
} catch {
case _ => 0
} finally {
println("always be printed")
}
}
def study_match(num:Int) = {
num match {
case 1 => "one"
case 2 => "two"
case _ => "other"
}
}
def main(args: Array[String]): Unit = {
// println(hello1("lilei"))
// study_for()
println(study_try())
println(study_match(1))
}
}
* 函数
/**
* 函数
*/
object functions {
//匿名函数
//(参数列表) => {函数体}
val sum1 = (a:Int,b:Int) => a + b
//函数
def sum2 (a:Int , b:Int) = a+b
//高阶函数1
def operate(f:(Int,Int) => Int) = {
f(4,4)
}
//高阶函数2
def greeting1() = (name:String) => {"hello" + " " + name}
def greeting2() = (name:String) => s"hello ${name}"
def main(args: Array[String]): Unit = {
println(sum1(3,4))
println(sum2(3,4))
println(operate(sum1))
println(greeting1()("world"))
println(greeting2()("IDEA"))
}
}
求值策略
两种方式:
- call by value - 对函数实参求值,且仅求值一次
- call by name - 函数实参每次在函数体内被用到才会求值(函数形参以 => 开头)
/**
* 求值策略
*/
object evaluation_strategy {
// x: call by value / y: call by name
def bar(x:Int, y: =>Int):Int = 1
def loop(): Int = loop
def main(args: Array[String]): Unit = {
println(bar(1,loop()))
// println(bar(loop(),1))
}
}
柯里化
/**
* 柯里化
*/
object curried {
// def add(x: Int, y: Int) = x + y //非科里化语法
// def add(x: Int)(y: Int) = x + y //科里化语法
/**
* 柯里化函数:把具有多个参数的函数转换为一条函数链,每个节点上是单一参数
* @ Curried Function
*/
def curriedAdd(a:Int)(b:Int) = a + b
val addOne = curriedAdd(1)_ //相当于从新定义了一个函数
def main(args: Array[String]): Unit = {
println(curriedAdd(2)(2))
println(addOne(2))
}
}
递归
/**
* 递归 recursive
*/
object recursive {
/**
* 递归函数
*/
def factorial1(n:Int): Int =
if(n <= 0) 1
else n * factorial1(n - 1)
/**
* 尾递归函数(Tail Recursive Function)
* 所有递归形式的调用出现在函数的末尾
* 当编译器检测到一个函数调用是尾递归,它就覆盖当前的活动记录而不是在栈中去创建一个新的
*/
@annotation.tailrec //告诉scala编译器要进行尾递归优化,不写的话不会主动优化
def factorial2(n:Int, m:Int):Int = // m记录每一回合后的阶乘
if (n <= 0) m
else factorial2(n-1 , m*n)
def main(args: Array[String]): Unit = {
println(factorial1(5))
println(factorial2(5,1))
}
}
Scala Immutable
list
/**
* List[T]
*/
object collections_list {
val a = List(1,2,3,4)
a.head //首元素
a.tail //尾列表(除了首元素)
a.isEmpty //判断是否为空
/**
* 遍历
* @param l
* @return
*/
def walkthru(l:List[Int]):String = {
if (l.isEmpty) ""
else l.head.toString + " " + walkthru(l.tail)
}
def main(args: Array[String]): Unit = {
println(a)
val b = 0::a //连接操作符 => 成员 :: List
println(b)
val c = a:::b
println(c)
val d =walkthru(a)
println(d)
val e = a.filter(x => x%2==1 )
println(e)
val str = "99 Red Balloons".toList
println(str)
println(str.filter(x => Character.isDigit(x)))
println(str.takeWhile(x => x!='B')) // 返回False的时候takeWhile停止
}
}
list-map
object list_map {
def main(args: Array[String]): Unit = {
// val c = List('x','y','z')
val c = "x"::"y"::"z"::Nil
// println(c.map(x => x.toUpperCase()))
println(c.map(_.toUpperCase()))
val a = List(1,2,3,4,5,6)
println(a.filter(_ % 2 == 1))
println(a.filter(_ % 2 == 1).map(_ + 10))
val q = List(List(1,2,3),List(4,5,6))
println(q.map(x => x.filter( _%2==0)))
println(q.map(_.filter( _%2==0))) //返回值类型跟原来的List一样
println(q.flatMap(_.filter( _%2==0))) //返回值类型是一个List
}
}
reduceLeft & flodLeft
/**
* 函数作为参数,函数参数 => 返回值
*/
object _Left {
def main(args: Array[String]): Unit = {
// reduceLeft(op: (T, T) => T)
val a = List(1,2,3,4,5)
println(a.reduceLeft((x,y) => x + y ))
println(a.reduceLeft(_+_))
// foldeLeft(z : U)(op: (U, T) => U)
println(a.foldLeft(0)(_+_))
}
}
Range
/**
* 整数序列
*/
object range {
def main(args: Array[String]): Unit = {
val a = 1 to 10
println(a)
println(a.toList)
val b = 1 to 10 by 2
println(b)
println(b.toList)
val c = 1 until 10
println(c.toList)
/*
to包含后边界,until不包含
*/
}
}
Stream
/**
* Stream is a lazy List
* 惰性求值的列表:
* 使用的时候才会处理,避免内存溢出
*/
object stream {
def main(args: Array[String]): Unit = {
val a = 1 #:: 2 #:: 3 #:: Stream.empty
println(a)
val stream = (1 to 1000000).toStream
println(stream)
println(stream.head)
println(stream.tail)
}
}
Tuple
/**
* Tuple 元组
*/
object tuple {
/**
* 1:长度
* 2:元素求和
* 3:元素平方和
*/
// foldeLeft(z : U)(op: (U, T) => U)
def sumSq(in: List[Int]):(Int,Int,Int) =
in.foldLeft((0,0,0))((t,v) => (t._1 + 1 , t._2 + v , t._3 + v*v))
def main(args: Array[String]): Unit = {
val a = (1,2)
println(a)
val b = 1->2
println(b)
val c = (1,"Alice","Math",95.5)
println(c)
println("1: "+c._1+"\t"+"2: "+c._2+"\t"+"3: "+c._3+"\t\t"+"4: "+c._4)
val arr = List(1,2,3,4,5)
println(sumSq(arr))
}
}
map
/**
* Map[K,V]
* map的基础操作
*/
object map {
def main(args: Array[String]): Unit = {
val m = Map(1->"David",2->"Alice",3->"Elwood")
println(m)
println(m(1))
/**
* value = map(key)
*/
// contains(key) 判断元素在不在map里
println(m.contains(4))
// 返回值为Set() => 返回所有的key
println(m.keys)
// 如上
println(m.values)
// 添加元素
val n = m + (8->"Archer")
println(n)
// 删除元素
val o = m - 1
println(o)
// 添加多个元素
val z = m ++ List(6->"test",7->"aaa")
println(z)
// 删除多个
var x = z -- List(1,6,7)
println(x)
var y = z ++ List(11->"eleven",12->"twelve") -- List(1,2,3,6,7)
println(y)
}
}
综合案例:
test1:
/**
* 函数::综合例子
*/
object test {
def sum( f:Int => Int)(a:Int)(b:Int) :Int = {
var num = 0
@annotation.tailrec
def loop(n:Int, acc:Int):Int = {
if (n > b) {
// println(s"n = ${n}\tacc=${acc}")
num = acc
acc
} else {
// println(s"n = ${n}\tacc=${acc}")
loop(n + 1, acc + f(n))
}
}
loop(a,0)
num
}
def main(args: Array[String]): Unit = {
println(sum(x => x)(1)(5))
println(sum(x => x*x)(1)(5))
println(sum(x => x*x*x)(1)(5))
}
}
quick sort:
object quickSort {
def qSort(a:List[Int]):List[Int] =
if (a.length < 2) a
else
qSort(a.filter(_ < a.head)) ++
a.filter( _ == a.head) ++
qSort(a.filter( _ > a.head))
def main(args: Array[String]): Unit = {
println(qSort(List(9,5,2,4,5,7,1,8,6,4)))
}
}
第一次接触函数式编程,感觉有些不同点需要消化一下。。。先记录下来。。。